sanity: Replace tabulars by spaces in *.cc *.hh *.hxx
* bin/autfilt.cc, bin/common_aoutput.cc, bin/common_aoutput.hh, bin/common_finput.cc, bin/common_finput.hh, bin/common_hoaread.cc, bin/common_output.cc, bin/common_output.hh, bin/common_post.cc, bin/common_post.hh, bin/common_r.hh, bin/common_range.cc, bin/common_range.hh, bin/common_setup.cc, bin/common_trans.cc, bin/common_trans.hh, bin/dstar2tgba.cc, bin/genltl.cc, bin/ltl2tgba.cc, bin/ltl2tgta.cc, bin/ltlcross.cc, bin/ltldo.cc, bin/ltlfilt.cc, bin/ltlgrind.cc, bin/randaut.cc, bin/randltl.cc, bin/spot-x.cc, spot/graph/graph.hh, spot/graph/ngraph.hh, spot/kripke/kripkegraph.hh, spot/ltsmin/ltsmin.cc, spot/ltsmin/ltsmin.hh, spot/misc/bareword.cc, spot/misc/bitvect.cc, spot/misc/bitvect.hh, spot/misc/common.hh, spot/misc/escape.cc, spot/misc/fixpool.hh, spot/misc/formater.cc, spot/misc/hash.hh, spot/misc/intvcmp2.cc, spot/misc/intvcmp2.hh, spot/misc/intvcomp.cc, spot/misc/intvcomp.hh, spot/misc/location.hh, spot/misc/minato.cc, spot/misc/minato.hh, spot/misc/mspool.hh, spot/misc/optionmap.cc, spot/misc/optionmap.hh, spot/misc/random.cc, spot/misc/random.hh, spot/misc/satsolver.cc, spot/misc/satsolver.hh, spot/misc/timer.cc, spot/misc/timer.hh, spot/misc/tmpfile.cc, spot/misc/trival.hh, spot/parseaut/fmterror.cc, spot/parseaut/parsedecl.hh, spot/parseaut/public.hh, spot/parsetl/fmterror.cc, spot/parsetl/parsedecl.hh, spot/priv/accmap.hh, spot/priv/bddalloc.cc, spot/priv/freelist.cc, spot/priv/trim.cc, spot/priv/weight.cc, spot/priv/weight.hh, spot/ta/taexplicit.cc, spot/ta/taexplicit.hh, spot/ta/taproduct.cc, spot/ta/taproduct.hh, spot/ta/tgtaexplicit.cc, spot/ta/tgtaexplicit.hh, spot/ta/tgtaproduct.cc, spot/ta/tgtaproduct.hh, spot/taalgos/dot.cc, spot/taalgos/dot.hh, spot/taalgos/emptinessta.cc, spot/taalgos/emptinessta.hh, spot/taalgos/minimize.cc, spot/taalgos/tgba2ta.cc, spot/taalgos/tgba2ta.hh, spot/tl/apcollect.cc, spot/tl/contain.cc, spot/tl/contain.hh, spot/tl/dot.cc, spot/tl/exclusive.cc, spot/tl/exclusive.hh, spot/tl/formula.cc, spot/tl/formula.hh, spot/tl/length.cc, spot/tl/mark.cc, spot/tl/mutation.cc, spot/tl/mutation.hh, spot/tl/parse.hh, spot/tl/print.cc, spot/tl/print.hh, spot/tl/randomltl.cc, spot/tl/randomltl.hh, spot/tl/relabel.cc, spot/tl/relabel.hh, spot/tl/remove_x.cc, spot/tl/simplify.cc, spot/tl/simplify.hh, spot/tl/snf.cc, spot/tl/snf.hh, spot/tl/unabbrev.cc, spot/tl/unabbrev.hh, spot/twa/acc.cc, spot/twa/acc.hh, spot/twa/bdddict.cc, spot/twa/bdddict.hh, spot/twa/bddprint.cc, spot/twa/formula2bdd.cc, spot/twa/formula2bdd.hh, spot/twa/taatgba.cc, spot/twa/taatgba.hh, spot/twa/twa.cc, spot/twa/twa.hh, spot/twa/twagraph.cc, spot/twa/twagraph.hh, spot/twa/twaproduct.cc, spot/twa/twaproduct.hh, spot/twaalgos/are_isomorphic.cc, spot/twaalgos/are_isomorphic.hh, spot/twaalgos/bfssteps.cc, spot/twaalgos/bfssteps.hh, spot/twaalgos/cleanacc.cc, spot/twaalgos/complete.cc, spot/twaalgos/compsusp.cc, spot/twaalgos/compsusp.hh, spot/twaalgos/copy.cc, spot/twaalgos/cycles.cc, spot/twaalgos/cycles.hh, spot/twaalgos/degen.cc, spot/twaalgos/degen.hh, spot/twaalgos/determinize.cc, spot/twaalgos/determinize.hh, spot/twaalgos/dot.cc, spot/twaalgos/dot.hh, spot/twaalgos/dtbasat.cc, spot/twaalgos/dtbasat.hh, spot/twaalgos/dtwasat.cc, spot/twaalgos/dtwasat.hh, spot/twaalgos/emptiness.cc, spot/twaalgos/emptiness.hh, spot/twaalgos/emptiness_stats.hh, spot/twaalgos/gtec/ce.cc, spot/twaalgos/gtec/ce.hh, spot/twaalgos/gtec/gtec.cc, spot/twaalgos/gtec/gtec.hh, spot/twaalgos/gtec/sccstack.cc, spot/twaalgos/gtec/status.cc, spot/twaalgos/gv04.cc, spot/twaalgos/hoa.cc, spot/twaalgos/hoa.hh, spot/twaalgos/isdet.cc, spot/twaalgos/isunamb.cc, spot/twaalgos/isweakscc.cc, spot/twaalgos/lbtt.cc, spot/twaalgos/lbtt.hh, spot/twaalgos/ltl2taa.cc, spot/twaalgos/ltl2taa.hh, spot/twaalgos/ltl2tgba_fm.cc, spot/twaalgos/ltl2tgba_fm.hh, spot/twaalgos/magic.cc, spot/twaalgos/magic.hh, spot/twaalgos/mask.cc, spot/twaalgos/mask.hh, spot/twaalgos/minimize.cc, spot/twaalgos/minimize.hh, spot/twaalgos/ndfs_result.hxx, spot/twaalgos/neverclaim.cc, spot/twaalgos/neverclaim.hh, spot/twaalgos/postproc.cc, spot/twaalgos/postproc.hh, spot/twaalgos/powerset.cc, spot/twaalgos/powerset.hh, spot/twaalgos/product.cc, spot/twaalgos/product.hh, spot/twaalgos/projrun.cc, spot/twaalgos/projrun.hh, spot/twaalgos/randomgraph.cc, spot/twaalgos/randomgraph.hh, spot/twaalgos/randomize.cc, spot/twaalgos/randomize.hh, spot/twaalgos/reachiter.cc, spot/twaalgos/reachiter.hh, spot/twaalgos/relabel.cc, spot/twaalgos/relabel.hh, spot/twaalgos/remfin.cc, spot/twaalgos/remprop.cc, spot/twaalgos/sbacc.cc, spot/twaalgos/sccfilter.cc, spot/twaalgos/sccfilter.hh, spot/twaalgos/sccinfo.cc, spot/twaalgos/sccinfo.hh, spot/twaalgos/se05.cc, spot/twaalgos/se05.hh, spot/twaalgos/sepsets.cc, spot/twaalgos/simulation.cc, spot/twaalgos/simulation.hh, spot/twaalgos/stats.cc, spot/twaalgos/stats.hh, spot/twaalgos/strength.cc, spot/twaalgos/strength.hh, spot/twaalgos/stripacc.cc, spot/twaalgos/stutter.cc, spot/twaalgos/stutter.hh, spot/twaalgos/tau03.cc, spot/twaalgos/tau03opt.cc, spot/twaalgos/tau03opt.hh, spot/twaalgos/totgba.cc, spot/twaalgos/translate.cc, spot/twaalgos/word.cc, tests/core/acc.cc, tests/core/bitvect.cc, tests/core/checkpsl.cc, tests/core/checkta.cc, tests/core/consterm.cc, tests/core/emptchk.cc, tests/core/equalsf.cc, tests/core/graph.cc, tests/core/ikwiad.cc, tests/core/intvcmp2.cc, tests/core/intvcomp.cc, tests/core/kind.cc, tests/core/kripkecat.cc, tests/core/ltlrel.cc, tests/core/ngraph.cc, tests/core/randtgba.cc, tests/core/readltl.cc, tests/core/reduc.cc, tests/core/safra.cc, tests/core/syntimpl.cc, tests/ltsmin/modelcheck.cc: Replace tabulars by 8 spaces. * tests/sanity/style.test: Add checks for no tabulars in *.cc *.hh *.hxx
This commit is contained in:
parent
1eee12b8b4
commit
f7e7b4f14e
239 changed files with 25359 additions and 25355 deletions
|
|
@ -47,7 +47,7 @@ namespace spot
|
|||
struct first_is_base_of<Of, Arg1, Args...>
|
||||
{
|
||||
static const bool value =
|
||||
std::is_base_of<Of, typename std::decay<Arg1>::type>::value;
|
||||
std::is_base_of<Of, typename std::decay<Arg1>::type>::value;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
@ -65,11 +65,11 @@ namespace spot
|
|||
|
||||
#ifndef SWIG
|
||||
template <typename... Args,
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<boxed_label, Args...>::value>::type>
|
||||
boxed_label(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Data, Args...>::value)
|
||||
: label{std::forward<Args>(args)...}
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<boxed_label, Args...>::value>::type>
|
||||
boxed_label(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Data, Args...>::value)
|
||||
: label{std::forward<Args>(args)...}
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
@ -77,23 +77,23 @@ namespace spot
|
|||
// if Data is a POD type, G++ 4.8.2 wants default values for all
|
||||
// label fields unless we define this default constructor here.
|
||||
explicit boxed_label()
|
||||
noexcept(std::is_nothrow_constructible<Data>::value)
|
||||
noexcept(std::is_nothrow_constructible<Data>::value)
|
||||
{
|
||||
}
|
||||
|
||||
Data& data()
|
||||
{
|
||||
return label;
|
||||
return label;
|
||||
}
|
||||
|
||||
const Data& data() const
|
||||
{
|
||||
return label;
|
||||
return label;
|
||||
}
|
||||
|
||||
bool operator<(const boxed_label& other) const
|
||||
{
|
||||
return label < other.label;
|
||||
return label < other.label;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -103,12 +103,12 @@ namespace spot
|
|||
typedef std::tuple<> data_t;
|
||||
std::tuple<>& data()
|
||||
{
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const std::tuple<>& data() const
|
||||
{
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -120,11 +120,11 @@ namespace spot
|
|||
|
||||
#ifndef SWIG
|
||||
template <typename... Args,
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<boxed_label, Args...>::value>::type>
|
||||
boxed_label(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Data, Args...>::value)
|
||||
: Data{std::forward<Args>(args)...}
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<boxed_label, Args...>::value>::type>
|
||||
boxed_label(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Data, Args...>::value)
|
||||
: Data{std::forward<Args>(args)...}
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
@ -132,18 +132,18 @@ namespace spot
|
|||
// if Data is a POD type, G++ 4.8.2 wants default values for all
|
||||
// label fields unless we define this default constructor here.
|
||||
explicit boxed_label()
|
||||
noexcept(std::is_nothrow_constructible<Data>::value)
|
||||
noexcept(std::is_nothrow_constructible<Data>::value)
|
||||
{
|
||||
}
|
||||
|
||||
Data& data()
|
||||
{
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Data& data() const
|
||||
{
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -158,15 +158,15 @@ namespace spot
|
|||
struct SPOT_API distate_storage final: public State_Data
|
||||
{
|
||||
Edge succ = 0; // First outgoing edge (used when iterating)
|
||||
Edge succ_tail = 0; // Last outgoing edge (used for
|
||||
// appending new edges)
|
||||
Edge succ_tail = 0; // Last outgoing edge (used for
|
||||
// appending new edges)
|
||||
#ifndef SWIG
|
||||
template <typename... Args,
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<distate_storage, Args...>::value>::type>
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<distate_storage, Args...>::value>::type>
|
||||
distate_storage(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<State_Data, Args...>::value)
|
||||
: State_Data{std::forward<Args>(args)...}
|
||||
noexcept(std::is_nothrow_constructible<State_Data, Args...>::value)
|
||||
: State_Data{std::forward<Args>(args)...}
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
@ -179,47 +179,47 @@ namespace spot
|
|||
// Again two implementation: one with label, and one without.
|
||||
|
||||
template <typename StateIn,
|
||||
typename StateOut, typename Edge, typename Edge_Data>
|
||||
typename StateOut, typename Edge, typename Edge_Data>
|
||||
struct SPOT_API edge_storage final: public Edge_Data
|
||||
{
|
||||
typedef Edge edge;
|
||||
|
||||
StateOut dst; // destination
|
||||
Edge next_succ; // next outgoing edge with same
|
||||
// source, or 0
|
||||
StateIn src; // source
|
||||
StateOut dst; // destination
|
||||
Edge next_succ; // next outgoing edge with same
|
||||
// source, or 0
|
||||
StateIn src; // source
|
||||
|
||||
explicit edge_storage()
|
||||
noexcept(std::is_nothrow_constructible<Edge_Data>::value)
|
||||
: Edge_Data{}
|
||||
noexcept(std::is_nothrow_constructible<Edge_Data>::value)
|
||||
: Edge_Data{}
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef SWIG
|
||||
template <typename... Args>
|
||||
edge_storage(StateOut dst, Edge next_succ,
|
||||
StateIn src, Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Edge_Data, Args...>::value
|
||||
&& std::is_nothrow_constructible<StateOut, StateOut>::value
|
||||
&& std::is_nothrow_constructible<Edge, Edge>::value)
|
||||
: Edge_Data{std::forward<Args>(args)...},
|
||||
dst(dst), next_succ(next_succ), src(src)
|
||||
StateIn src, Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Edge_Data, Args...>::value
|
||||
&& std::is_nothrow_constructible<StateOut, StateOut>::value
|
||||
&& std::is_nothrow_constructible<Edge, Edge>::value)
|
||||
: Edge_Data{std::forward<Args>(args)...},
|
||||
dst(dst), next_succ(next_succ), src(src)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator<(const edge_storage& other) const
|
||||
{
|
||||
if (src < other.src)
|
||||
return true;
|
||||
if (src > other.src)
|
||||
return false;
|
||||
// This might be costly if the destination is a vector
|
||||
if (dst < other.dst)
|
||||
return true;
|
||||
if (dst > other.dst)
|
||||
return false;
|
||||
return this->data() < other.data();
|
||||
if (src < other.src)
|
||||
return true;
|
||||
if (src > other.src)
|
||||
return false;
|
||||
// This might be costly if the destination is a vector
|
||||
if (dst < other.dst)
|
||||
return true;
|
||||
if (dst > other.dst)
|
||||
return false;
|
||||
return this->data() < other.data();
|
||||
}
|
||||
|
||||
bool operator==(const edge_storage& other) const
|
||||
|
|
@ -241,86 +241,86 @@ namespace spot
|
|||
template <typename Graph>
|
||||
class SPOT_API edge_iterator: public
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
{
|
||||
typedef
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
super;
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
super;
|
||||
public:
|
||||
typedef typename Graph::edge edge;
|
||||
|
||||
edge_iterator() noexcept
|
||||
: g_(nullptr), t_(0)
|
||||
: g_(nullptr), t_(0)
|
||||
{
|
||||
}
|
||||
|
||||
edge_iterator(Graph* g, edge t) noexcept
|
||||
: g_(g), t_(t)
|
||||
: g_(g), t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(edge_iterator o) const
|
||||
{
|
||||
return t_ == o.t_;
|
||||
return t_ == o.t_;
|
||||
}
|
||||
|
||||
bool operator!=(edge_iterator o) const
|
||||
{
|
||||
return t_ != o.t_;
|
||||
return t_ != o.t_;
|
||||
}
|
||||
|
||||
typename super::reference
|
||||
operator*()
|
||||
{
|
||||
return g_->edge_storage(t_);
|
||||
return g_->edge_storage(t_);
|
||||
}
|
||||
|
||||
const typename super::reference
|
||||
operator*() const
|
||||
{
|
||||
return g_->edge_storage(t_);
|
||||
return g_->edge_storage(t_);
|
||||
}
|
||||
|
||||
typename super::pointer
|
||||
operator->()
|
||||
{
|
||||
return &g_->edge_storage(t_);
|
||||
return &g_->edge_storage(t_);
|
||||
}
|
||||
|
||||
const typename super::pointer
|
||||
operator->() const
|
||||
{
|
||||
return &g_->edge_storage(t_);
|
||||
return &g_->edge_storage(t_);
|
||||
}
|
||||
|
||||
edge_iterator operator++()
|
||||
{
|
||||
t_ = operator*().next_succ;
|
||||
return *this;
|
||||
t_ = operator*().next_succ;
|
||||
return *this;
|
||||
}
|
||||
|
||||
edge_iterator operator++(int)
|
||||
{
|
||||
edge_iterator ti = *this;
|
||||
t_ = operator*().next_succ;
|
||||
return ti;
|
||||
edge_iterator ti = *this;
|
||||
t_ = operator*().next_succ;
|
||||
return ti;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return t_;
|
||||
return t_;
|
||||
}
|
||||
|
||||
edge trans() const
|
||||
{
|
||||
return t_;
|
||||
return t_;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -337,52 +337,52 @@ namespace spot
|
|||
typedef typename Graph::edge edge;
|
||||
|
||||
killer_edge_iterator(Graph* g, edge t, state_storage_t& src) noexcept
|
||||
: super(g, t), src_(src), prev_(0)
|
||||
: super(g, t), src_(src), prev_(0)
|
||||
{
|
||||
}
|
||||
|
||||
killer_edge_iterator operator++()
|
||||
{
|
||||
prev_ = this->t_;
|
||||
this->t_ = this->operator*().next_succ;
|
||||
return *this;
|
||||
prev_ = this->t_;
|
||||
this->t_ = this->operator*().next_succ;
|
||||
return *this;
|
||||
}
|
||||
|
||||
killer_edge_iterator operator++(int)
|
||||
{
|
||||
killer_edge_iterator ti = *this;
|
||||
++*this;
|
||||
return ti;
|
||||
killer_edge_iterator ti = *this;
|
||||
++*this;
|
||||
return ti;
|
||||
}
|
||||
|
||||
// Erase the current edge and advance the iterator.
|
||||
void erase()
|
||||
{
|
||||
edge next = this->operator*().next_succ;
|
||||
edge next = this->operator*().next_succ;
|
||||
|
||||
// Update source state and previous edges
|
||||
if (prev_)
|
||||
{
|
||||
this->g_->edge_storage(prev_).next_succ = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (src_.succ == this->t_)
|
||||
src_.succ = next;
|
||||
}
|
||||
if (src_.succ_tail == this->t_)
|
||||
{
|
||||
src_.succ_tail = prev_;
|
||||
assert(next == 0);
|
||||
}
|
||||
// Update source state and previous edges
|
||||
if (prev_)
|
||||
{
|
||||
this->g_->edge_storage(prev_).next_succ = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (src_.succ == this->t_)
|
||||
src_.succ = next;
|
||||
}
|
||||
if (src_.succ_tail == this->t_)
|
||||
{
|
||||
src_.succ_tail = prev_;
|
||||
assert(next == 0);
|
||||
}
|
||||
|
||||
// Erased edges have themselves as next_succ.
|
||||
this->operator*().next_succ = this->t_;
|
||||
// Erased edges have themselves as next_succ.
|
||||
this->operator*().next_succ = this->t_;
|
||||
|
||||
// Advance iterator to next edge.
|
||||
this->t_ = next;
|
||||
// Advance iterator to next edge.
|
||||
this->t_ = next;
|
||||
|
||||
++this->g_->killed_edge_;
|
||||
++this->g_->killed_edge_;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -403,23 +403,23 @@ namespace spot
|
|||
public:
|
||||
typedef typename Graph::edge edge;
|
||||
state_out(Graph* g, edge t) noexcept
|
||||
: g_(g), t_(t)
|
||||
: g_(g), t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
edge_iterator<Graph> begin()
|
||||
{
|
||||
return {g_, t_};
|
||||
return {g_, t_};
|
||||
}
|
||||
|
||||
edge_iterator<Graph> end()
|
||||
{
|
||||
return {};
|
||||
return {};
|
||||
}
|
||||
|
||||
void recycle(edge t)
|
||||
{
|
||||
t_ = t;
|
||||
t_ = t;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -434,92 +434,92 @@ namespace spot
|
|||
template <typename Graph>
|
||||
class SPOT_API all_edge_iterator: public
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
{
|
||||
typedef
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
super;
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
super;
|
||||
|
||||
typedef typename std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_vector_t,
|
||||
typename Graph::edge_vector_t>::type
|
||||
tv_t;
|
||||
const typename Graph::edge_vector_t,
|
||||
typename Graph::edge_vector_t>::type
|
||||
tv_t;
|
||||
|
||||
unsigned t_;
|
||||
tv_t& tv_;
|
||||
|
||||
void skip_()
|
||||
{
|
||||
unsigned s = tv_.size();
|
||||
do
|
||||
++t_;
|
||||
while (t_ < s && tv_[t_].next_succ == t_);
|
||||
unsigned s = tv_.size();
|
||||
do
|
||||
++t_;
|
||||
while (t_ < s && tv_[t_].next_succ == t_);
|
||||
}
|
||||
|
||||
public:
|
||||
all_edge_iterator(unsigned pos, tv_t& tv) noexcept
|
||||
: t_(pos), tv_(tv)
|
||||
: t_(pos), tv_(tv)
|
||||
{
|
||||
skip_();
|
||||
skip_();
|
||||
}
|
||||
|
||||
all_edge_iterator(tv_t& tv) noexcept
|
||||
: t_(tv.size()), tv_(tv)
|
||||
: t_(tv.size()), tv_(tv)
|
||||
{
|
||||
}
|
||||
|
||||
all_edge_iterator& operator++()
|
||||
{
|
||||
skip_();
|
||||
return *this;
|
||||
skip_();
|
||||
return *this;
|
||||
}
|
||||
|
||||
all_edge_iterator operator++(int)
|
||||
{
|
||||
all_edge_iterator old = *this;
|
||||
++*this;
|
||||
return old;
|
||||
all_edge_iterator old = *this;
|
||||
++*this;
|
||||
return old;
|
||||
}
|
||||
|
||||
bool operator==(all_edge_iterator o) const
|
||||
{
|
||||
return t_ == o.t_;
|
||||
return t_ == o.t_;
|
||||
}
|
||||
|
||||
bool operator!=(all_edge_iterator o) const
|
||||
{
|
||||
return t_ != o.t_;
|
||||
return t_ != o.t_;
|
||||
}
|
||||
|
||||
typename super::reference
|
||||
operator*()
|
||||
{
|
||||
return tv_[t_];
|
||||
return tv_[t_];
|
||||
}
|
||||
|
||||
const typename super::reference
|
||||
operator*() const
|
||||
{
|
||||
return tv_[t_];
|
||||
return tv_[t_];
|
||||
}
|
||||
|
||||
const typename super::pointer
|
||||
operator->()
|
||||
{
|
||||
return &tv_[t_];
|
||||
return &tv_[t_];
|
||||
}
|
||||
|
||||
typename super::pointer
|
||||
operator->() const
|
||||
{
|
||||
return &tv_[t_];
|
||||
return &tv_[t_];
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -529,27 +529,27 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
typedef typename std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_vector_t,
|
||||
typename Graph::edge_vector_t>::type
|
||||
tv_t;
|
||||
const typename Graph::edge_vector_t,
|
||||
typename Graph::edge_vector_t>::type
|
||||
tv_t;
|
||||
typedef all_edge_iterator<Graph> iter_t;
|
||||
private:
|
||||
tv_t& tv_;
|
||||
public:
|
||||
|
||||
all_trans(tv_t& tv) noexcept
|
||||
: tv_(tv)
|
||||
: tv_(tv)
|
||||
{
|
||||
}
|
||||
|
||||
iter_t begin()
|
||||
{
|
||||
return {0, tv_};
|
||||
return {0, tv_};
|
||||
}
|
||||
|
||||
iter_t end()
|
||||
{
|
||||
return {tv_};
|
||||
return {tv_};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -586,14 +586,14 @@ namespace spot
|
|||
// The type of an output state (when seen from a edge)
|
||||
// depends on the kind of graph we build
|
||||
typedef typename std::conditional<Alternating,
|
||||
std::vector<state>,
|
||||
state>::type out_state;
|
||||
std::vector<state>,
|
||||
state>::type out_state;
|
||||
|
||||
typedef internal::distate_storage<edge,
|
||||
internal::boxed_label<State_Data>>
|
||||
internal::boxed_label<State_Data>>
|
||||
state_storage_t;
|
||||
typedef internal::edge_storage<state, out_state, edge,
|
||||
internal::boxed_label<Edge_Data>>
|
||||
internal::boxed_label<Edge_Data>>
|
||||
edge_storage_t;
|
||||
typedef std::vector<state_storage_t> state_vector;
|
||||
typedef std::vector<edge_storage_t> edge_vector_t;
|
||||
|
|
@ -614,7 +614,7 @@ namespace spot
|
|||
{
|
||||
states_.reserve(max_states);
|
||||
if (max_trans == 0)
|
||||
max_trans = max_states * 2;
|
||||
max_trans = max_states * 2;
|
||||
edges_.reserve(max_trans + 1);
|
||||
// Edge number 0 is not used, because we use this index
|
||||
// to mark the absence of a edge.
|
||||
|
|
@ -638,7 +638,7 @@ namespace spot
|
|||
// Erased edges have their next_succ pointing to
|
||||
// themselves.
|
||||
return (t < edges_.size() &&
|
||||
edges_[t].next_succ != t);
|
||||
edges_[t].next_succ != t);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
|
|
@ -655,7 +655,7 @@ namespace spot
|
|||
state s = states_.size();
|
||||
states_.reserve(s + n);
|
||||
while (n--)
|
||||
states_.emplace_back(std::forward<Args>(args)...);
|
||||
states_.emplace_back(std::forward<Args>(args)...);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
@ -730,9 +730,9 @@ namespace spot
|
|||
edge st = states_[src].succ_tail;
|
||||
assert(st < t || !st);
|
||||
if (!st)
|
||||
states_[src].succ = t;
|
||||
states_[src].succ = t;
|
||||
else
|
||||
edges_[st].next_succ = t;
|
||||
edges_[st].next_succ = t;
|
||||
states_[src].succ_tail = t;
|
||||
return t;
|
||||
}
|
||||
|
|
@ -836,19 +836,19 @@ namespace spot
|
|||
{
|
||||
unsigned tend = edges_.size();
|
||||
for (unsigned t = 1; t < tend; ++t)
|
||||
{
|
||||
o << 't' << t << ": (s"
|
||||
<< edges_[t].src << ", s"
|
||||
<< edges_[t].dst << ") t"
|
||||
<< edges_[t].next_succ << '\n';
|
||||
}
|
||||
{
|
||||
o << 't' << t << ": (s"
|
||||
<< edges_[t].src << ", s"
|
||||
<< edges_[t].dst << ") t"
|
||||
<< edges_[t].next_succ << '\n';
|
||||
}
|
||||
unsigned send = states_.size();
|
||||
for (unsigned s = 0; s < send; ++s)
|
||||
{
|
||||
o << 's' << s << ": t"
|
||||
<< states_[s].succ << " t"
|
||||
<< states_[s].succ_tail << '\n';
|
||||
}
|
||||
{
|
||||
o << 's' << s << ": t"
|
||||
<< states_[s].succ << " t"
|
||||
<< states_[s].succ_tail << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all dead edges. The edges_ vector is left
|
||||
|
|
@ -858,11 +858,11 @@ namespace spot
|
|||
void remove_dead_edges_()
|
||||
{
|
||||
if (killed_edge_ == 0)
|
||||
return;
|
||||
return;
|
||||
auto i = std::remove_if(edges_.begin() + 1, edges_.end(),
|
||||
[this](const edge_storage_t& t) {
|
||||
return this->is_dead_edge(t);
|
||||
});
|
||||
[this](const edge_storage_t& t) {
|
||||
return this->is_dead_edge(t);
|
||||
});
|
||||
edges_.erase(i, edges_.end());
|
||||
killed_edge_ = 0;
|
||||
}
|
||||
|
|
@ -885,38 +885,38 @@ namespace spot
|
|||
state last_src = -1U;
|
||||
edge tend = edges_.size();
|
||||
for (edge t = 1; t < tend; ++t)
|
||||
{
|
||||
state src = edges_[t].src;
|
||||
if (src != last_src)
|
||||
{
|
||||
states_[src].succ = t;
|
||||
if (last_src != -1U)
|
||||
{
|
||||
states_[last_src].succ_tail = t - 1;
|
||||
edges_[t - 1].next_succ = 0;
|
||||
}
|
||||
while (++last_src != src)
|
||||
{
|
||||
states_[last_src].succ = 0;
|
||||
states_[last_src].succ_tail = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
edges_[t - 1].next_succ = t;
|
||||
}
|
||||
}
|
||||
{
|
||||
state src = edges_[t].src;
|
||||
if (src != last_src)
|
||||
{
|
||||
states_[src].succ = t;
|
||||
if (last_src != -1U)
|
||||
{
|
||||
states_[last_src].succ_tail = t - 1;
|
||||
edges_[t - 1].next_succ = 0;
|
||||
}
|
||||
while (++last_src != src)
|
||||
{
|
||||
states_[last_src].succ = 0;
|
||||
states_[last_src].succ_tail = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
edges_[t - 1].next_succ = t;
|
||||
}
|
||||
}
|
||||
if (last_src != -1U)
|
||||
{
|
||||
states_[last_src].succ_tail = tend - 1;
|
||||
edges_[tend - 1].next_succ = 0;
|
||||
}
|
||||
{
|
||||
states_[last_src].succ_tail = tend - 1;
|
||||
edges_[tend - 1].next_succ = 0;
|
||||
}
|
||||
unsigned send = states_.size();
|
||||
while (++last_src != send)
|
||||
{
|
||||
states_[last_src].succ = 0;
|
||||
states_[last_src].succ_tail = 0;
|
||||
}
|
||||
{
|
||||
states_[last_src].succ = 0;
|
||||
states_[last_src].succ_tail = 0;
|
||||
}
|
||||
//std::cerr << "\nafter\n";
|
||||
//dump_storage(std::cerr);
|
||||
}
|
||||
|
|
@ -930,10 +930,10 @@ namespace spot
|
|||
assert(newst.size() == states_.size());
|
||||
unsigned tend = edges_.size();
|
||||
for (unsigned t = 1; t < tend; t++)
|
||||
{
|
||||
edges_[t].dst = newst[edges_[t].dst];
|
||||
edges_[t].src = newst[edges_[t].src];
|
||||
}
|
||||
{
|
||||
edges_[t].dst = newst[edges_[t].dst];
|
||||
edges_[t].src = newst[edges_[t].src];
|
||||
}
|
||||
}
|
||||
|
||||
void defrag_states(std::vector<unsigned>&& newst, unsigned used_states)
|
||||
|
|
@ -947,22 +947,22 @@ namespace spot
|
|||
// Shift all states in states_, as indicated by newst.
|
||||
unsigned send = states_.size();
|
||||
for (state s = 0; s < send; ++s)
|
||||
{
|
||||
state dst = newst[s];
|
||||
if (dst == s)
|
||||
continue;
|
||||
if (dst == -1U)
|
||||
{
|
||||
// This is an erased state. Mark all its edges as
|
||||
// dead (i.e., t.next_succ should point to t for each of
|
||||
// them).
|
||||
auto t = states_[s].succ;
|
||||
while (t)
|
||||
std::swap(t, edges_[t].next_succ);
|
||||
continue;
|
||||
}
|
||||
states_[dst] = std::move(states_[s]);
|
||||
}
|
||||
{
|
||||
state dst = newst[s];
|
||||
if (dst == s)
|
||||
continue;
|
||||
if (dst == -1U)
|
||||
{
|
||||
// This is an erased state. Mark all its edges as
|
||||
// dead (i.e., t.next_succ should point to t for each of
|
||||
// them).
|
||||
auto t = states_[s].succ;
|
||||
while (t)
|
||||
std::swap(t, edges_[t].next_succ);
|
||||
continue;
|
||||
}
|
||||
states_[dst] = std::move(states_[s]);
|
||||
}
|
||||
states_.resize(used_states);
|
||||
|
||||
// Shift all edges in edges_. The algorithm is
|
||||
|
|
@ -972,33 +972,33 @@ namespace spot
|
|||
std::vector<edge> newidx(tend);
|
||||
unsigned dest = 1;
|
||||
for (edge t = 1; t < tend; ++t)
|
||||
{
|
||||
if (is_dead_edge(t))
|
||||
continue;
|
||||
if (t != dest)
|
||||
edges_[dest] = std::move(edges_[t]);
|
||||
newidx[t] = dest;
|
||||
++dest;
|
||||
}
|
||||
{
|
||||
if (is_dead_edge(t))
|
||||
continue;
|
||||
if (t != dest)
|
||||
edges_[dest] = std::move(edges_[t]);
|
||||
newidx[t] = dest;
|
||||
++dest;
|
||||
}
|
||||
edges_.resize(dest);
|
||||
killed_edge_ = 0;
|
||||
|
||||
// Adjust next_succ and dst pointers in all edges.
|
||||
for (edge t = 1; t < dest; ++t)
|
||||
{
|
||||
auto& tr = edges_[t];
|
||||
tr.next_succ = newidx[tr.next_succ];
|
||||
tr.dst = newst[tr.dst];
|
||||
tr.src = newst[tr.src];
|
||||
assert(tr.dst != -1U);
|
||||
}
|
||||
{
|
||||
auto& tr = edges_[t];
|
||||
tr.next_succ = newidx[tr.next_succ];
|
||||
tr.dst = newst[tr.dst];
|
||||
tr.src = newst[tr.src];
|
||||
assert(tr.dst != -1U);
|
||||
}
|
||||
|
||||
// Adjust succ and succ_tails pointers in all states.
|
||||
for (auto& s: states_)
|
||||
{
|
||||
s.succ = newidx[s.succ];
|
||||
s.succ_tail = newidx[s.succ_tail];
|
||||
}
|
||||
{
|
||||
s.succ = newidx[s.succ];
|
||||
s.succ_tail = newidx[s.succ_tail];
|
||||
}
|
||||
|
||||
//std::cerr << "\nafter defrag\n";
|
||||
//dump_storage(std::cerr);
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@
|
|||
namespace spot
|
||||
{
|
||||
template <typename Graph,
|
||||
typename State_Name,
|
||||
typename Name_Hash = std::hash<State_Name>,
|
||||
typename Name_Equal = std::equal_to<State_Name>>
|
||||
typename State_Name,
|
||||
typename Name_Hash = std::hash<State_Name>,
|
||||
typename Name_Equal = std::equal_to<State_Name>>
|
||||
class SPOT_API named_graph
|
||||
{
|
||||
protected:
|
||||
|
|
@ -40,7 +40,7 @@ namespace spot
|
|||
typedef State_Name name;
|
||||
|
||||
typedef std::unordered_map<name, state,
|
||||
Name_Hash, Name_Equal> name_to_state_t;
|
||||
Name_Hash, Name_Equal> name_to_state_t;
|
||||
name_to_state_t name_to_state;
|
||||
typedef std::vector<name> state_to_name_t;
|
||||
state_to_name_t state_to_name;
|
||||
|
|
@ -65,14 +65,14 @@ namespace spot
|
|||
{
|
||||
auto p = name_to_state.emplace(n, 0U);
|
||||
if (p.second)
|
||||
{
|
||||
unsigned s = g_.new_state(std::forward<Args>(args)...);
|
||||
p.first->second = s;
|
||||
if (state_to_name.size() < s + 1)
|
||||
state_to_name.resize(s + 1);
|
||||
state_to_name[s] = n;
|
||||
return s;
|
||||
}
|
||||
{
|
||||
unsigned s = g_.new_state(std::forward<Args>(args)...);
|
||||
p.first->second = s;
|
||||
if (state_to_name.size() < s + 1)
|
||||
state_to_name.resize(s + 1);
|
||||
state_to_name[s] = n;
|
||||
return s;
|
||||
}
|
||||
return p.first->second;
|
||||
}
|
||||
|
||||
|
|
@ -85,27 +85,27 @@ namespace spot
|
|||
{
|
||||
auto p = name_to_state.emplace(newname, s);
|
||||
if (!p.second)
|
||||
{
|
||||
// The state already exists. Change its number.
|
||||
auto old = p.first->second;
|
||||
p.first->second = s;
|
||||
// Add the successor of OLD to those of S.
|
||||
auto& trans = g_.edge_vector();
|
||||
auto& states = g_.states();
|
||||
trans[states[s].succ_tail].next_succ = states[old].succ;
|
||||
states[s].succ_tail = states[old].succ_tail;
|
||||
states[old].succ = 0;
|
||||
states[old].succ_tail = 0;
|
||||
// Remove all references to old in edges:
|
||||
unsigned tend = trans.size();
|
||||
for (unsigned t = 1; t < tend; ++t)
|
||||
{
|
||||
if (trans[t].src == old)
|
||||
trans[t].src = s;
|
||||
if (trans[t].dst == old)
|
||||
trans[t].dst = s;
|
||||
}
|
||||
}
|
||||
{
|
||||
// The state already exists. Change its number.
|
||||
auto old = p.first->second;
|
||||
p.first->second = s;
|
||||
// Add the successor of OLD to those of S.
|
||||
auto& trans = g_.edge_vector();
|
||||
auto& states = g_.states();
|
||||
trans[states[s].succ_tail].next_succ = states[old].succ;
|
||||
states[s].succ_tail = states[old].succ_tail;
|
||||
states[old].succ = 0;
|
||||
states[old].succ_tail = 0;
|
||||
// Remove all references to old in edges:
|
||||
unsigned tend = trans.size();
|
||||
for (unsigned t = 1; t < tend; ++t)
|
||||
{
|
||||
if (trans[t].src == old)
|
||||
trans[t].src = s;
|
||||
if (trans[t].dst == old)
|
||||
trans[t].dst = s;
|
||||
}
|
||||
}
|
||||
return !p.second;
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ namespace spot
|
|||
new_edge(name src, name dst, Args&&... args)
|
||||
{
|
||||
return g_.new_edge(get_state(src), get_state(dst),
|
||||
std::forward<Args>(args)...);
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
|
|
@ -144,19 +144,19 @@ namespace spot
|
|||
std::vector<State_Name> d;
|
||||
d.reserve(dst.size());
|
||||
for (auto n: dst)
|
||||
d.push_back(get_state(n));
|
||||
d.push_back(get_state(n));
|
||||
return g_.new_edge(get_state(src), d, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
edge
|
||||
new_edge(name src,
|
||||
const std::initializer_list<State_Name>& dst, Args&&... args)
|
||||
const std::initializer_list<State_Name>& dst, Args&&... args)
|
||||
{
|
||||
std::vector<state> d;
|
||||
d.reserve(dst.size());
|
||||
for (auto n: dst)
|
||||
d.push_back(get_state(n));
|
||||
d.push_back(get_state(n));
|
||||
return g_.new_edge(get_state(src), d, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,16 +46,16 @@ namespace spot
|
|||
|
||||
// Do not simply return "other - this", it might not fit in an int.
|
||||
if (o < this)
|
||||
return -1;
|
||||
return -1;
|
||||
if (o > this)
|
||||
return 1;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t hash() const override
|
||||
{
|
||||
return
|
||||
reinterpret_cast<const char*>(this) - static_cast<const char*>(nullptr);
|
||||
reinterpret_cast<const char*>(this) - static_cast<const char*>(nullptr);
|
||||
}
|
||||
|
||||
virtual kripke_graph_state*
|
||||
|
|
@ -93,7 +93,7 @@ namespace spot
|
|||
edge p_;
|
||||
public:
|
||||
kripke_graph_succ_iterator(const Graph* g,
|
||||
const typename Graph::state_storage_t* s):
|
||||
const typename Graph::state_storage_t* s):
|
||||
kripke_succ_iterator(s->cond()),
|
||||
g_(g),
|
||||
t_(s->succ)
|
||||
|
|
@ -131,7 +131,7 @@ namespace spot
|
|||
{
|
||||
assert(!done());
|
||||
return const_cast<kripke_graph_state*>
|
||||
(&g_->state_data(g_->edge_storage(p_).dst));
|
||||
(&g_->state_data(g_->edge_storage(p_).dst));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -176,14 +176,14 @@ namespace spot
|
|||
graph_t::state get_init_state_number() const
|
||||
{
|
||||
if (num_states() == 0)
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
return init_number_;
|
||||
}
|
||||
|
||||
virtual const kripke_graph_state* get_init_state() const override
|
||||
{
|
||||
if (num_states() == 0)
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
return state_from_number(init_number_);
|
||||
}
|
||||
|
||||
|
|
@ -197,13 +197,13 @@ namespace spot
|
|||
assert(!s->succ || g_.valid_trans(s->succ));
|
||||
|
||||
if (this->iter_cache_)
|
||||
{
|
||||
auto it =
|
||||
down_cast<kripke_graph_succ_iterator<graph_t>*>(this->iter_cache_);
|
||||
it->recycle(s);
|
||||
this->iter_cache_ = nullptr;
|
||||
return it;
|
||||
}
|
||||
{
|
||||
auto it =
|
||||
down_cast<kripke_graph_succ_iterator<graph_t>*>(this->iter_cache_);
|
||||
it->recycle(s);
|
||||
this->iter_cache_ = nullptr;
|
||||
return it;
|
||||
}
|
||||
return new kripke_graph_succ_iterator<graph_t>(&g_, s);
|
||||
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -67,9 +67,9 @@ namespace spot
|
|||
// to enable compression, 2 to enable a faster compression that only
|
||||
// work if all variables are smaller than 2^28.
|
||||
kripke_ptr kripke(const atomic_prop_set* to_observe,
|
||||
bdd_dict_ptr dict,
|
||||
formula dead = formula::tt(),
|
||||
int compress = 0) const;
|
||||
bdd_dict_ptr dict,
|
||||
formula dead = formula::tt(),
|
||||
int compress = 0) const;
|
||||
|
||||
/// Number of variables in a state
|
||||
int state_size() const;
|
||||
|
|
|
|||
|
|
@ -32,12 +32,12 @@ namespace spot
|
|||
{
|
||||
// Bare words cannot be empty and should start with a letter.
|
||||
if (!*str
|
||||
|| !(isalpha(*str) || *str == '_' || *str == '.'))
|
||||
|| !(isalpha(*str) || *str == '_' || *str == '.'))
|
||||
return false;
|
||||
// The remaining of the word must be alphanumeric.
|
||||
while (*++str)
|
||||
if (!(isalnum(*str) || *str == '_' || *str == '.'))
|
||||
return false;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ namespace spot
|
|||
return false;
|
||||
while (*++str)
|
||||
if (!(isalnum(*str) || *str == '_'))
|
||||
return false;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace spot
|
|||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t n = (bitcount + bpb - 1) / bpb;
|
||||
if (n < 1)
|
||||
return 1;
|
||||
return 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
@ -60,12 +60,12 @@ namespace spot
|
|||
{
|
||||
static unsigned long init()
|
||||
{
|
||||
return 14695981039346656037UL;
|
||||
return 14695981039346656037UL;
|
||||
}
|
||||
|
||||
static unsigned long prime()
|
||||
{
|
||||
return 1099511628211UL;
|
||||
return 1099511628211UL;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
|
@ -76,12 +76,12 @@ namespace spot
|
|||
{
|
||||
static unsigned long init()
|
||||
{
|
||||
return 2166136261UL;
|
||||
return 2166136261UL;
|
||||
}
|
||||
|
||||
static unsigned long prime()
|
||||
{
|
||||
return 16777619UL;
|
||||
return 16777619UL;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ namespace spot
|
|||
// already contains one int of local_storage_, but
|
||||
// we allocate n-1 more so that we store the table.
|
||||
void* mem = operator new(sizeof(bitvect)
|
||||
+ (n - 1) * sizeof(bitvect::block_t));
|
||||
+ (n - 1) * sizeof(bitvect::block_t));
|
||||
bitvect* res = new(mem) bitvect(size_, n, true);
|
||||
memcpy(res->storage_, storage_, res->block_count_ * sizeof(block_t));
|
||||
return res;
|
||||
|
|
@ -125,8 +125,8 @@ namespace spot
|
|||
return res;
|
||||
for (i = 0; i < m - 1; ++i)
|
||||
{
|
||||
res ^= storage_[i];
|
||||
res *= fnv<sizeof(block_t)>::prime();
|
||||
res ^= storage_[i];
|
||||
res *= fnv<sizeof(block_t)>::prime();
|
||||
}
|
||||
// Deal with the last block, that might not be fully used.
|
||||
// Compute the number n of bits used in the last block.
|
||||
|
|
@ -144,7 +144,7 @@ namespace spot
|
|||
// already contains one int of local_storage_, but
|
||||
// we allocate n-1 more so that we store the table.
|
||||
void* mem = operator new(sizeof(bitvect)
|
||||
+ (n - 1) * sizeof(bitvect::block_t));
|
||||
+ (n - 1) * sizeof(bitvect::block_t));
|
||||
return new(mem) bitvect(bitcount, n);
|
||||
}
|
||||
|
||||
|
|
@ -176,16 +176,16 @@ namespace spot
|
|||
size_t end = a.size();
|
||||
if (end == 0)
|
||||
{
|
||||
os << "empty\n";
|
||||
return os;
|
||||
os << "empty\n";
|
||||
return os;
|
||||
}
|
||||
int w = floor(log10(end - 1)) + 1;
|
||||
for (size_t i = 0; i != end; ++i)
|
||||
{
|
||||
os.width(w);
|
||||
os << i;
|
||||
os.width(1);
|
||||
os << ": " << a.at(i) << '\n';
|
||||
os.width(w);
|
||||
os << i;
|
||||
os.width(1);
|
||||
os << ": " << a.at(i) << '\n';
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace spot
|
|||
///
|
||||
/// The resulting bitvect_array should be released with <code>delete</code>.
|
||||
SPOT_API bitvect_array* make_bitvect_array(size_t bitcount,
|
||||
size_t vectcount);
|
||||
size_t vectcount);
|
||||
|
||||
/// \brief A bit vector
|
||||
class SPOT_API bitvect
|
||||
|
|
@ -85,14 +85,14 @@ namespace spot
|
|||
reserve_blocks(other.block_count_);
|
||||
size_ = other.size();
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
storage_[i] = other.storage_[i];
|
||||
storage_[i] = other.storage_[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
~bitvect()
|
||||
{
|
||||
if (storage_ != &local_storage_)
|
||||
free(storage_);
|
||||
free(storage_);
|
||||
}
|
||||
|
||||
/// Grow the bitvector to \a new_block_count blocks.
|
||||
|
|
@ -101,20 +101,20 @@ namespace spot
|
|||
void reserve_blocks(size_t new_block_count)
|
||||
{
|
||||
if (new_block_count < block_count_)
|
||||
return;
|
||||
return;
|
||||
if (storage_ == &local_storage_)
|
||||
{
|
||||
block_t* new_storage_ = static_cast<block_t*>
|
||||
(malloc(new_block_count * sizeof(block_t)));
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
new_storage_[i] = storage_[i];
|
||||
storage_ = new_storage_;
|
||||
}
|
||||
{
|
||||
block_t* new_storage_ = static_cast<block_t*>
|
||||
(malloc(new_block_count * sizeof(block_t)));
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
new_storage_[i] = storage_[i];
|
||||
storage_ = new_storage_;
|
||||
}
|
||||
else
|
||||
{
|
||||
storage_ = static_cast<block_t*>
|
||||
(realloc(storage_, new_block_count * sizeof(block_t)));
|
||||
}
|
||||
{
|
||||
storage_ = static_cast<block_t*>
|
||||
(realloc(storage_, new_block_count * sizeof(block_t)));
|
||||
}
|
||||
block_count_ = new_block_count;
|
||||
}
|
||||
|
||||
|
|
@ -137,44 +137,44 @@ namespace spot
|
|||
void push_back(bool val)
|
||||
{
|
||||
if (size() == capacity())
|
||||
grow();
|
||||
grow();
|
||||
size_t pos = size_++;
|
||||
if (val)
|
||||
set(pos);
|
||||
set(pos);
|
||||
else
|
||||
clear(pos);
|
||||
clear(pos);
|
||||
}
|
||||
|
||||
/// \brief Append the lowest \a count bits of \a data.
|
||||
void push_back(block_t data, unsigned count)
|
||||
{
|
||||
if (size() + count > capacity())
|
||||
grow();
|
||||
grow();
|
||||
const size_t bpb = 8 * sizeof(block_t);
|
||||
|
||||
// Clear the higher bits.
|
||||
if (count != bpb)
|
||||
data &= (1UL << count) - 1;
|
||||
data &= (1UL << count) - 1;
|
||||
|
||||
size_t n = size() % bpb;
|
||||
size_t i = size_ / bpb;
|
||||
size_ += count;
|
||||
if (n == 0) // Aligned on block_t boundary
|
||||
{
|
||||
storage_[i] = data;
|
||||
}
|
||||
else // Only (bpb-n) bits free in this block.
|
||||
{
|
||||
// Take the lower bpb-n bits of data...
|
||||
block_t mask = (1UL << (bpb - n)) - 1;
|
||||
block_t data1 = (data & mask) << n;
|
||||
mask <<= n;
|
||||
// ... write them on the higher bpb-n bits of last block.
|
||||
storage_[i] = (storage_[i] & ~mask) | data1;
|
||||
// Write the remaining bits in the next block.
|
||||
if (bpb - n < count)
|
||||
storage_[i + 1] = data >> (bpb - n);
|
||||
}
|
||||
if (n == 0) // Aligned on block_t boundary
|
||||
{
|
||||
storage_[i] = data;
|
||||
}
|
||||
else // Only (bpb-n) bits free in this block.
|
||||
{
|
||||
// Take the lower bpb-n bits of data...
|
||||
block_t mask = (1UL << (bpb - n)) - 1;
|
||||
block_t data1 = (data & mask) << n;
|
||||
mask <<= n;
|
||||
// ... write them on the higher bpb-n bits of last block.
|
||||
storage_[i] = (storage_[i] & ~mask) | data1;
|
||||
// Write the remaining bits in the next block.
|
||||
if (bpb - n < count)
|
||||
storage_[i + 1] = data >> (bpb - n);
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
|
|
@ -199,7 +199,7 @@ namespace spot
|
|||
void clear_all()
|
||||
{
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
storage_[i] = 0;
|
||||
storage_[i] = 0;
|
||||
}
|
||||
|
||||
bool is_fully_clear() const
|
||||
|
|
@ -208,12 +208,12 @@ namespace spot
|
|||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (i = 0; i < block_count_ - !!rest; ++i)
|
||||
if (storage_[i] != 0)
|
||||
return false;
|
||||
if (storage_[i] != 0)
|
||||
return false;
|
||||
// The last block might not be fully used, compare only the
|
||||
// relevant portion.
|
||||
if (!rest)
|
||||
return true;
|
||||
return true;
|
||||
block_t mask = (1UL << rest) - 1;
|
||||
return (storage_[i] & mask) == 0;
|
||||
}
|
||||
|
|
@ -224,10 +224,10 @@ namespace spot
|
|||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (i = 0; i < block_count_ - !!rest; ++i)
|
||||
if (storage_[i] != -1UL)
|
||||
return false;
|
||||
if (storage_[i] != -1UL)
|
||||
return false;
|
||||
if (!rest)
|
||||
return true;
|
||||
return true;
|
||||
// The last block might not be fully used, compare only the
|
||||
// relevant portion.
|
||||
block_t mask = (1UL << rest) - 1;
|
||||
|
|
@ -237,13 +237,13 @@ namespace spot
|
|||
void set_all()
|
||||
{
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
storage_[i] = -1UL;
|
||||
storage_[i] = -1UL;
|
||||
}
|
||||
|
||||
void flip_all()
|
||||
{
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
storage_[i] = ~storage_[i];
|
||||
storage_[i] = ~storage_[i];
|
||||
}
|
||||
|
||||
void set(size_t pos)
|
||||
|
|
@ -273,7 +273,7 @@ namespace spot
|
|||
assert(other.size_ <= size_);
|
||||
unsigned m = std::min(other.block_count_, block_count_);
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
storage_[i] |= other.storage_[i];
|
||||
storage_[i] |= other.storage_[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -282,7 +282,7 @@ namespace spot
|
|||
assert(other.size_ <= size_);
|
||||
unsigned m = std::min(other.block_count_, block_count_);
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
storage_[i] &= other.storage_[i];
|
||||
storage_[i] &= other.storage_[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ namespace spot
|
|||
assert(other.size_ <= size_);
|
||||
unsigned m = std::min(other.block_count_, block_count_);
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
storage_[i] ^= other.storage_[i];
|
||||
storage_[i] ^= other.storage_[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -299,7 +299,7 @@ namespace spot
|
|||
{
|
||||
assert(other.block_count_ <= block_count_);
|
||||
for (size_t i = 0; i < other.block_count_; ++i)
|
||||
storage_[i] &= ~other.storage_[i];
|
||||
storage_[i] &= ~other.storage_[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -311,33 +311,33 @@ namespace spot
|
|||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (i = 0; i < block_count_ - !!rest; ++i)
|
||||
if ((storage_[i] & other.storage_[i]) != other.storage_[i])
|
||||
return false;
|
||||
if ((storage_[i] & other.storage_[i]) != other.storage_[i])
|
||||
return false;
|
||||
if (!rest)
|
||||
return true;
|
||||
return true;
|
||||
|
||||
// The last block might not be fully used, compare only the
|
||||
// relevant portion.
|
||||
block_t mask = (1UL << rest) - 1;
|
||||
return ((storage_[i] & mask & other.storage_[i])
|
||||
== (other.storage_[i] & mask));
|
||||
== (other.storage_[i] & mask));
|
||||
}
|
||||
|
||||
bool operator==(const bitvect& other) const
|
||||
{
|
||||
if (other.size_ != size_)
|
||||
return false;
|
||||
return false;
|
||||
if (size_ == 0)
|
||||
return true;
|
||||
return true;
|
||||
size_t i;
|
||||
size_t m = other.used_blocks();
|
||||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (i = 0; i < m - !!rest; ++i)
|
||||
if (storage_[i] != other.storage_[i])
|
||||
return false;
|
||||
if (storage_[i] != other.storage_[i])
|
||||
return false;
|
||||
if (!rest)
|
||||
return true;
|
||||
return true;
|
||||
// The last block might not be fully used, compare only the
|
||||
// relevant portion.
|
||||
block_t mask = (1UL << rest) - 1;
|
||||
|
|
@ -352,18 +352,18 @@ namespace spot
|
|||
bool operator<(const bitvect& other) const
|
||||
{
|
||||
if (size_ != other.size_)
|
||||
return size_ < other.size_;
|
||||
return size_ < other.size_;
|
||||
if (size_ == 0)
|
||||
return false;
|
||||
return false;
|
||||
size_t i;
|
||||
size_t m = other.used_blocks();
|
||||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (i = 0; i < m - !!rest; ++i)
|
||||
if (storage_[i] > other.storage_[i])
|
||||
return false;
|
||||
if (storage_[i] > other.storage_[i])
|
||||
return false;
|
||||
if (!rest)
|
||||
return true;
|
||||
return true;
|
||||
// The last block might not be fully used, compare only the
|
||||
// relevant portion.
|
||||
block_t mask = (1UL << rest) - 1;
|
||||
|
|
@ -398,7 +398,7 @@ namespace spot
|
|||
res->make_empty();
|
||||
|
||||
if (end == begin)
|
||||
return res;
|
||||
return res;
|
||||
|
||||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
|
||||
|
|
@ -407,32 +407,32 @@ namespace spot
|
|||
size_t indexe = (end - 1) / bpb;
|
||||
|
||||
if (indexb == indexe)
|
||||
{
|
||||
block_t data = storage_[indexb];
|
||||
data >>= bitb;
|
||||
res->push_back(data, count);
|
||||
}
|
||||
{
|
||||
block_t data = storage_[indexb];
|
||||
data >>= bitb;
|
||||
res->push_back(data, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
block_t data = storage_[indexb];
|
||||
data >>= bitb;
|
||||
res->push_back(data, bpb - bitb);
|
||||
count -= bpb - bitb;
|
||||
while (count >= bpb)
|
||||
{
|
||||
++indexb;
|
||||
res->push_back(storage_[indexb], bpb);
|
||||
count -= bpb;
|
||||
assert(indexb != indexe || count == 0);
|
||||
}
|
||||
if (count > 0)
|
||||
{
|
||||
++indexb;
|
||||
assert(indexb == indexe);
|
||||
assert(count == end % bpb);
|
||||
res->push_back(storage_[indexb], count);
|
||||
}
|
||||
}
|
||||
{
|
||||
block_t data = storage_[indexb];
|
||||
data >>= bitb;
|
||||
res->push_back(data, bpb - bitb);
|
||||
count -= bpb - bitb;
|
||||
while (count >= bpb)
|
||||
{
|
||||
++indexb;
|
||||
res->push_back(storage_[indexb], bpb);
|
||||
count -= bpb;
|
||||
assert(indexb != indexe || count == 0);
|
||||
}
|
||||
if (count > 0)
|
||||
{
|
||||
++indexb;
|
||||
assert(indexb == indexe);
|
||||
assert(count == end % bpb);
|
||||
res->push_back(storage_[indexb], count);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -441,12 +441,12 @@ namespace spot
|
|||
|
||||
/// Print a bitvect.
|
||||
friend SPOT_API std::ostream& operator<<(std::ostream&,
|
||||
const bitvect&);
|
||||
const bitvect&);
|
||||
|
||||
private:
|
||||
friend SPOT_API bitvect_array*
|
||||
::spot::make_bitvect_array(size_t bitcount,
|
||||
size_t vectcount);
|
||||
size_t vectcount);
|
||||
|
||||
size_t size_;
|
||||
size_t block_count_;
|
||||
|
|
@ -485,7 +485,7 @@ namespace spot
|
|||
~bitvect_array()
|
||||
{
|
||||
for (size_t i = 0; i < size_; ++i)
|
||||
at(i).~bitvect();
|
||||
at(i).~bitvect();
|
||||
}
|
||||
|
||||
/// The number of bitvect in the array.
|
||||
|
|
@ -506,7 +506,7 @@ namespace spot
|
|||
// FIXME: This could be changed into a large memset if the
|
||||
// individual vectors where not allowed to be reallocated.
|
||||
for (unsigned s = 0; s < size_; s++)
|
||||
at(s).clear_all();
|
||||
at(s).clear_all();
|
||||
}
|
||||
|
||||
/// Return the bit-vector at \a index.
|
||||
|
|
@ -518,12 +518,12 @@ namespace spot
|
|||
|
||||
friend SPOT_API bitvect_array*
|
||||
::spot::make_bitvect_array(size_t bitcount,
|
||||
size_t vectcount);
|
||||
size_t vectcount);
|
||||
|
||||
|
||||
/// Print a bitvect_array.
|
||||
friend SPOT_API std::ostream& operator<<(std::ostream&,
|
||||
const bitvect_array&);
|
||||
const bitvect_array&);
|
||||
|
||||
private:
|
||||
size_t size_;
|
||||
|
|
|
|||
|
|
@ -93,9 +93,9 @@
|
|||
|
||||
// The extra parentheses in assert() is so that this
|
||||
// pattern is not caught by the style checker.
|
||||
#define SPOT_UNREACHABLE() do { \
|
||||
assert(!("unreachable code reached")); \
|
||||
SPOT_UNREACHABLE_BUILTIN(); \
|
||||
#define SPOT_UNREACHABLE() do { \
|
||||
assert(!("unreachable code reached")); \
|
||||
SPOT_UNREACHABLE_BUILTIN(); \
|
||||
} while (0)
|
||||
|
||||
#define SPOT_UNIMPLEMENTED() throw std::runtime_error("unimplemented");
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ namespace spot
|
|||
{
|
||||
for (auto i: str)
|
||||
switch (i)
|
||||
{
|
||||
case '"':
|
||||
os << "\"\"";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
{
|
||||
case '"':
|
||||
os << "\"\"";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
@ -49,28 +49,28 @@ namespace spot
|
|||
{
|
||||
for (auto i: str)
|
||||
switch (i)
|
||||
{
|
||||
case '~':
|
||||
os << "\\text{\\textasciitilde}";
|
||||
break;
|
||||
case '^':
|
||||
os << "\\text{\\textasciicircum}";
|
||||
break;
|
||||
case '\\':
|
||||
os << "\\text{\\textbackslash}";
|
||||
break;
|
||||
case '&':
|
||||
case '%':
|
||||
case '$':
|
||||
case '#':
|
||||
case '_':
|
||||
case '{':
|
||||
case '}':
|
||||
os << '\\';
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
{
|
||||
case '~':
|
||||
os << "\\text{\\textasciitilde}";
|
||||
break;
|
||||
case '^':
|
||||
os << "\\text{\\textasciicircum}";
|
||||
break;
|
||||
case '\\':
|
||||
os << "\\text{\\textbackslash}";
|
||||
break;
|
||||
case '&':
|
||||
case '%':
|
||||
case '$':
|
||||
case '#':
|
||||
case '_':
|
||||
case '{':
|
||||
case '}':
|
||||
os << '\\';
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
@ -79,23 +79,23 @@ namespace spot
|
|||
{
|
||||
for (auto i: str)
|
||||
switch (i)
|
||||
{
|
||||
case '&':
|
||||
os << "&";
|
||||
break;
|
||||
case '"':
|
||||
os << """;
|
||||
break;
|
||||
case '<':
|
||||
os << "<";
|
||||
break;
|
||||
case '>':
|
||||
os << ">";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
{
|
||||
case '&':
|
||||
os << "&";
|
||||
break;
|
||||
case '"':
|
||||
os << """;
|
||||
break;
|
||||
case '<':
|
||||
os << "<";
|
||||
break;
|
||||
case '>':
|
||||
os << ">";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
@ -104,20 +104,20 @@ namespace spot
|
|||
{
|
||||
for (auto i: str)
|
||||
switch (i)
|
||||
{
|
||||
case '\\':
|
||||
os << "\\\\";
|
||||
break;
|
||||
case '"':
|
||||
os << "\\\"";
|
||||
break;
|
||||
case '\n':
|
||||
os << "\\n";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
{
|
||||
case '\\':
|
||||
os << "\\\\";
|
||||
break;
|
||||
case '"':
|
||||
os << "\\\"";
|
||||
break;
|
||||
case '\n':
|
||||
os << "\\n";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
@ -135,26 +135,26 @@ namespace spot
|
|||
// Single quotes are best, unless the string to quote contains one.
|
||||
if (!strchr(str, '\''))
|
||||
{
|
||||
os << '\'' << str << '\'';
|
||||
os << '\'' << str << '\'';
|
||||
}
|
||||
else
|
||||
{
|
||||
// In double quotes we have to escape $ ` " or \.
|
||||
os << '"';
|
||||
while (*str)
|
||||
switch (*str)
|
||||
{
|
||||
case '$':
|
||||
case '`':
|
||||
case '"':
|
||||
case '\\':
|
||||
os << '\\';
|
||||
// fall through
|
||||
default:
|
||||
os << *str++;
|
||||
break;
|
||||
}
|
||||
os << '"';
|
||||
// In double quotes we have to escape $ ` " or \.
|
||||
os << '"';
|
||||
while (*str)
|
||||
switch (*str)
|
||||
{
|
||||
case '$':
|
||||
case '`':
|
||||
case '"':
|
||||
case '\\':
|
||||
os << '\\';
|
||||
// fall through
|
||||
default:
|
||||
os << *str++;
|
||||
break;
|
||||
}
|
||||
os << '"';
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,22 +34,22 @@ namespace spot
|
|||
/// Create a pool allocating objects of \a size bytes.
|
||||
fixed_size_pool(size_t size)
|
||||
: freelist_(nullptr), free_start_(nullptr),
|
||||
free_end_(nullptr), chunklist_(nullptr)
|
||||
free_end_(nullptr), chunklist_(nullptr)
|
||||
{
|
||||
const size_t alignement = 2 * sizeof(size_t);
|
||||
size_ = ((size >= sizeof(block_) ? size : sizeof(block_))
|
||||
+ alignement - 1) & ~(alignement - 1);
|
||||
+ alignement - 1) & ~(alignement - 1);
|
||||
}
|
||||
|
||||
/// Free any memory allocated by this pool.
|
||||
~fixed_size_pool()
|
||||
{
|
||||
while (chunklist_)
|
||||
{
|
||||
chunk_* prev = chunklist_->prev;
|
||||
free(chunklist_);
|
||||
chunklist_ = prev;
|
||||
}
|
||||
{
|
||||
chunk_* prev = chunklist_->prev;
|
||||
free(chunklist_);
|
||||
chunklist_ = prev;
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocate \a size bytes of memory.
|
||||
|
|
@ -59,27 +59,27 @@ namespace spot
|
|||
block_* f = freelist_;
|
||||
// If we have free blocks available, return the first one.
|
||||
if (f)
|
||||
{
|
||||
freelist_ = f->next;
|
||||
return f;
|
||||
}
|
||||
{
|
||||
freelist_ = f->next;
|
||||
return f;
|
||||
}
|
||||
|
||||
// Else, create a block out of the last chunk of allocated
|
||||
// memory.
|
||||
|
||||
// If all the last chunk has been used, allocate one more.
|
||||
if (free_start_ + size_ > free_end_)
|
||||
{
|
||||
const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64;
|
||||
chunk_* c = reinterpret_cast<chunk_*>(malloc(requested));
|
||||
if (!c)
|
||||
throw std::bad_alloc();
|
||||
c->prev = chunklist_;
|
||||
chunklist_ = c;
|
||||
{
|
||||
const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64;
|
||||
chunk_* c = reinterpret_cast<chunk_*>(malloc(requested));
|
||||
if (!c)
|
||||
throw std::bad_alloc();
|
||||
c->prev = chunklist_;
|
||||
chunklist_ = c;
|
||||
|
||||
free_start_ = c->data_ + size_;
|
||||
free_end_ = c->data_ + requested;
|
||||
}
|
||||
free_start_ = c->data_ + size_;
|
||||
free_end_ = c->data_ + requested;
|
||||
}
|
||||
|
||||
void* res = free_start_;
|
||||
free_start_ += size_;
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ namespace spot
|
|||
{
|
||||
for (const char* pos = fmt; *pos; ++pos)
|
||||
if (*pos == '%')
|
||||
{
|
||||
char c = *++pos;
|
||||
has[c] = true;
|
||||
if (!c)
|
||||
break;
|
||||
}
|
||||
{
|
||||
char c = *++pos;
|
||||
has[c] = true;
|
||||
if (!c)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -46,17 +46,17 @@ namespace spot
|
|||
formater::format(const char* fmt)
|
||||
{
|
||||
for (const char* pos = fmt; *pos; ++pos)
|
||||
if (*pos != '%')
|
||||
{
|
||||
*output_ << *pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
char c = *++pos;
|
||||
call_[c]->print(*output_, pos);
|
||||
if (!c)
|
||||
break;
|
||||
}
|
||||
if (*pos != '%')
|
||||
{
|
||||
*output_ << *pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
char c = *++pos;
|
||||
call_[c]->print(*output_, pos);
|
||||
if (!c)
|
||||
break;
|
||||
}
|
||||
return *output_;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ namespace spot
|
|||
size_t operator()(const T* p) const
|
||||
{
|
||||
return knuth32_hash(reinterpret_cast<const char*>(p)
|
||||
- static_cast<const char*>(nullptr));
|
||||
- static_cast<const char*>(nullptr));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ namespace spot
|
|||
std::hash<U> uh;
|
||||
|
||||
return wang32_hash(static_cast<size_t>(th(p.first)) ^
|
||||
static_cast<size_t>(uh(p.second)));
|
||||
static_cast<size_t>(uh(p.second)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,270 +43,270 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
stream_compression_base(size_t size)
|
||||
: size_(size)
|
||||
: size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
static const unsigned bits_width[7] = { 1, 3, 5, 7, 9, 14, 28 };
|
||||
static const unsigned max_count[8] = { 30, 10, 6, 4, 3, 2, 1, 0 };
|
||||
static const unsigned max_allowed[8] = { 1,
|
||||
(1 << 3) - 1,
|
||||
(1 << 5) - 1,
|
||||
(1 << 7) - 1,
|
||||
(1 << 9) - 1,
|
||||
(1 << 14) - 1,
|
||||
(1 << 28) - 1,
|
||||
-1U };
|
||||
// If we have only X data to compress and they fit with the
|
||||
// current bit width, the following table tells us we should
|
||||
// use bits_width[count_to_level[X - 1]] to limit the number
|
||||
// of trailing zeros we encode. E.g. count_to_level[5 - 1]
|
||||
// is 2, which mean that 5 values should be encoded with
|
||||
// bits_width[2] == 5 bits.
|
||||
static const unsigned count_to_level[30] =
|
||||
{
|
||||
6, // 1
|
||||
5, // 2
|
||||
4, // 3
|
||||
3, // 4
|
||||
2, // 5
|
||||
2, // 6
|
||||
1, // 7
|
||||
1, // 8
|
||||
1, // 9
|
||||
1, // 10
|
||||
0, 0, 0, 0, 0, // 11-15
|
||||
0, 0, 0, 0, 0, // 16-20
|
||||
0, 0, 0, 0, 0, // 21-25
|
||||
0, 0, 0, 0, 0, // 26-30
|
||||
};
|
||||
static const unsigned bits_width[7] = { 1, 3, 5, 7, 9, 14, 28 };
|
||||
static const unsigned max_count[8] = { 30, 10, 6, 4, 3, 2, 1, 0 };
|
||||
static const unsigned max_allowed[8] = { 1,
|
||||
(1 << 3) - 1,
|
||||
(1 << 5) - 1,
|
||||
(1 << 7) - 1,
|
||||
(1 << 9) - 1,
|
||||
(1 << 14) - 1,
|
||||
(1 << 28) - 1,
|
||||
-1U };
|
||||
// If we have only X data to compress and they fit with the
|
||||
// current bit width, the following table tells us we should
|
||||
// use bits_width[count_to_level[X - 1]] to limit the number
|
||||
// of trailing zeros we encode. E.g. count_to_level[5 - 1]
|
||||
// is 2, which mean that 5 values should be encoded with
|
||||
// bits_width[2] == 5 bits.
|
||||
static const unsigned count_to_level[30] =
|
||||
{
|
||||
6, // 1
|
||||
5, // 2
|
||||
4, // 3
|
||||
3, // 4
|
||||
2, // 5
|
||||
2, // 6
|
||||
1, // 7
|
||||
1, // 8
|
||||
1, // 9
|
||||
1, // 10
|
||||
0, 0, 0, 0, 0, // 11-15
|
||||
0, 0, 0, 0, 0, // 16-20
|
||||
0, 0, 0, 0, 0, // 21-25
|
||||
0, 0, 0, 0, 0, // 26-30
|
||||
};
|
||||
|
||||
while (size_ > 0)
|
||||
{
|
||||
unsigned id = 0; // Current level in the above two tables.
|
||||
unsigned curmax_allowed = max_allowed[id];
|
||||
unsigned compressable = 0; // Number of integers ready to pack.
|
||||
do
|
||||
{
|
||||
unsigned int val = self().data_at(compressable);
|
||||
++compressable;
|
||||
while (val > curmax_allowed)
|
||||
{
|
||||
curmax_allowed = max_allowed[++id];
|
||||
while (size_ > 0)
|
||||
{
|
||||
unsigned id = 0; // Current level in the above two tables.
|
||||
unsigned curmax_allowed = max_allowed[id];
|
||||
unsigned compressable = 0; // Number of integers ready to pack.
|
||||
do
|
||||
{
|
||||
unsigned int val = self().data_at(compressable);
|
||||
++compressable;
|
||||
while (val > curmax_allowed)
|
||||
{
|
||||
curmax_allowed = max_allowed[++id];
|
||||
|
||||
if (compressable > max_count[id])
|
||||
goto fast_encode;
|
||||
}
|
||||
if (compressable >= max_count[id])
|
||||
goto fast_encode;
|
||||
}
|
||||
while (SPOT_LIKELY(compressable < size_));
|
||||
if (compressable > max_count[id])
|
||||
goto fast_encode;
|
||||
}
|
||||
if (compressable >= max_count[id])
|
||||
goto fast_encode;
|
||||
}
|
||||
while (SPOT_LIKELY(compressable < size_));
|
||||
|
||||
assert(compressable < max_count[id]);
|
||||
assert(compressable < max_count[id]);
|
||||
|
||||
// Since we have less data than the current "id" allows,
|
||||
// try to use more bits so we can encode faster.
|
||||
// Since we have less data than the current "id" allows,
|
||||
// try to use more bits so we can encode faster.
|
||||
|
||||
id = count_to_level[compressable - 1];
|
||||
id = count_to_level[compressable - 1];
|
||||
|
||||
if (compressable == max_count[id])
|
||||
goto fast_encode;
|
||||
if (compressable == max_count[id])
|
||||
goto fast_encode;
|
||||
|
||||
// Slow compression for situations where we have
|
||||
// compressable < max_count[id]. We can only be in
|
||||
// one of the 3 first "id" (1, 3, or 5 bits);
|
||||
{
|
||||
assert(id <= 2);
|
||||
unsigned bits = bits_width[id];
|
||||
unsigned finalshifts = (max_count[id] - compressable) * bits;
|
||||
size_t pos = 0;
|
||||
unsigned output = self().data_at(pos);
|
||||
while (--compressable)
|
||||
{
|
||||
output <<= bits;
|
||||
output += self().data_at(++pos);
|
||||
}
|
||||
output <<= finalshifts;
|
||||
output += id << 30;
|
||||
self().push_data(output);
|
||||
return;
|
||||
}
|
||||
// Slow compression for situations where we have
|
||||
// compressable < max_count[id]. We can only be in
|
||||
// one of the 3 first "id" (1, 3, or 5 bits);
|
||||
{
|
||||
assert(id <= 2);
|
||||
unsigned bits = bits_width[id];
|
||||
unsigned finalshifts = (max_count[id] - compressable) * bits;
|
||||
size_t pos = 0;
|
||||
unsigned output = self().data_at(pos);
|
||||
while (--compressable)
|
||||
{
|
||||
output <<= bits;
|
||||
output += self().data_at(++pos);
|
||||
}
|
||||
output <<= finalshifts;
|
||||
output += id << 30;
|
||||
self().push_data(output);
|
||||
return;
|
||||
}
|
||||
|
||||
fast_encode:
|
||||
switch (id)
|
||||
{
|
||||
case 0: // 30 1-bit values
|
||||
{
|
||||
// This code has been tuned so that the compiler can
|
||||
// efficiently encode it as a series of MOV+LEA
|
||||
// instructions, without shifts. For instance
|
||||
//
|
||||
// output <<= 1;
|
||||
// output += self().data_at(4);
|
||||
//
|
||||
// translates to (assuming %eax points to the input,
|
||||
// and %edx holds the output) the following:
|
||||
//
|
||||
// mov ecx, [eax+16]
|
||||
// lea edx, [ecx+edx*2]
|
||||
//
|
||||
// This optimization is the reason why we use 'output +='
|
||||
// instead of the more intuitive 'output |=' everywhere in
|
||||
// this file.
|
||||
fast_encode:
|
||||
switch (id)
|
||||
{
|
||||
case 0: // 30 1-bit values
|
||||
{
|
||||
// This code has been tuned so that the compiler can
|
||||
// efficiently encode it as a series of MOV+LEA
|
||||
// instructions, without shifts. For instance
|
||||
//
|
||||
// output <<= 1;
|
||||
// output += self().data_at(4);
|
||||
//
|
||||
// translates to (assuming %eax points to the input,
|
||||
// and %edx holds the output) the following:
|
||||
//
|
||||
// mov ecx, [eax+16]
|
||||
// lea edx, [ecx+edx*2]
|
||||
//
|
||||
// This optimization is the reason why we use 'output +='
|
||||
// instead of the more intuitive 'output |=' everywhere in
|
||||
// this file.
|
||||
|
||||
unsigned int output = 0x00 << 1; // 00
|
||||
output += self().data_at(0);
|
||||
output <<= 1;
|
||||
output += self().data_at(1);
|
||||
output <<= 1;
|
||||
output += self().data_at(2);
|
||||
output <<= 1;
|
||||
output += self().data_at(3);
|
||||
output <<= 1;
|
||||
output += self().data_at(4);
|
||||
output <<= 1;
|
||||
output += self().data_at(5);
|
||||
output <<= 1;
|
||||
output += self().data_at(6);
|
||||
output <<= 1;
|
||||
output += self().data_at(7);
|
||||
output <<= 1;
|
||||
output += self().data_at(8);
|
||||
output <<= 1;
|
||||
output += self().data_at(9);
|
||||
output <<= 1;
|
||||
output += self().data_at(10);
|
||||
output <<= 1;
|
||||
output += self().data_at(11);
|
||||
output <<= 1;
|
||||
output += self().data_at(12);
|
||||
output <<= 1;
|
||||
output += self().data_at(13);
|
||||
output <<= 1;
|
||||
output += self().data_at(14);
|
||||
output <<= 1;
|
||||
output += self().data_at(15);
|
||||
output <<= 1;
|
||||
output += self().data_at(16);
|
||||
output <<= 1;
|
||||
output += self().data_at(17);
|
||||
output <<= 1;
|
||||
output += self().data_at(18);
|
||||
output <<= 1;
|
||||
output += self().data_at(19);
|
||||
output <<= 1;
|
||||
output += self().data_at(20);
|
||||
output <<= 1;
|
||||
output += self().data_at(21);
|
||||
output <<= 1;
|
||||
output += self().data_at(22);
|
||||
output <<= 1;
|
||||
output += self().data_at(23);
|
||||
output <<= 1;
|
||||
output += self().data_at(24);
|
||||
output <<= 1;
|
||||
output += self().data_at(25);
|
||||
output <<= 1;
|
||||
output += self().data_at(26);
|
||||
output <<= 1;
|
||||
output += self().data_at(27);
|
||||
output <<= 1;
|
||||
output += self().data_at(28);
|
||||
output <<= 1;
|
||||
output += self().data_at(29);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 1: // 10 3-bit values
|
||||
{
|
||||
// This code has been tuned so that the compiler can
|
||||
// efficiently encode it as a series of MOV+LEA
|
||||
// instructions, without shifts. For instance
|
||||
//
|
||||
// output <<= 3;
|
||||
// output += self().data_at(4);
|
||||
//
|
||||
// translates to (assuming %eax points to the input,
|
||||
// and %edx holds the output) the following:
|
||||
//
|
||||
// mov ecx, [eax+16]
|
||||
// lea edx, [ecx+edx*8]
|
||||
unsigned int output = 0x00 << 1; // 00
|
||||
output += self().data_at(0);
|
||||
output <<= 1;
|
||||
output += self().data_at(1);
|
||||
output <<= 1;
|
||||
output += self().data_at(2);
|
||||
output <<= 1;
|
||||
output += self().data_at(3);
|
||||
output <<= 1;
|
||||
output += self().data_at(4);
|
||||
output <<= 1;
|
||||
output += self().data_at(5);
|
||||
output <<= 1;
|
||||
output += self().data_at(6);
|
||||
output <<= 1;
|
||||
output += self().data_at(7);
|
||||
output <<= 1;
|
||||
output += self().data_at(8);
|
||||
output <<= 1;
|
||||
output += self().data_at(9);
|
||||
output <<= 1;
|
||||
output += self().data_at(10);
|
||||
output <<= 1;
|
||||
output += self().data_at(11);
|
||||
output <<= 1;
|
||||
output += self().data_at(12);
|
||||
output <<= 1;
|
||||
output += self().data_at(13);
|
||||
output <<= 1;
|
||||
output += self().data_at(14);
|
||||
output <<= 1;
|
||||
output += self().data_at(15);
|
||||
output <<= 1;
|
||||
output += self().data_at(16);
|
||||
output <<= 1;
|
||||
output += self().data_at(17);
|
||||
output <<= 1;
|
||||
output += self().data_at(18);
|
||||
output <<= 1;
|
||||
output += self().data_at(19);
|
||||
output <<= 1;
|
||||
output += self().data_at(20);
|
||||
output <<= 1;
|
||||
output += self().data_at(21);
|
||||
output <<= 1;
|
||||
output += self().data_at(22);
|
||||
output <<= 1;
|
||||
output += self().data_at(23);
|
||||
output <<= 1;
|
||||
output += self().data_at(24);
|
||||
output <<= 1;
|
||||
output += self().data_at(25);
|
||||
output <<= 1;
|
||||
output += self().data_at(26);
|
||||
output <<= 1;
|
||||
output += self().data_at(27);
|
||||
output <<= 1;
|
||||
output += self().data_at(28);
|
||||
output <<= 1;
|
||||
output += self().data_at(29);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 1: // 10 3-bit values
|
||||
{
|
||||
// This code has been tuned so that the compiler can
|
||||
// efficiently encode it as a series of MOV+LEA
|
||||
// instructions, without shifts. For instance
|
||||
//
|
||||
// output <<= 3;
|
||||
// output += self().data_at(4);
|
||||
//
|
||||
// translates to (assuming %eax points to the input,
|
||||
// and %edx holds the output) the following:
|
||||
//
|
||||
// mov ecx, [eax+16]
|
||||
// lea edx, [ecx+edx*8]
|
||||
|
||||
unsigned int output = 0x01 << 3; // 01
|
||||
output += self().data_at(0);
|
||||
output <<= 3;
|
||||
output += self().data_at(1);
|
||||
output <<= 3;
|
||||
output += self().data_at(2);
|
||||
output <<= 3;
|
||||
output += self().data_at(3);
|
||||
output <<= 3;
|
||||
output += self().data_at(4);
|
||||
output <<= 3;
|
||||
output += self().data_at(5);
|
||||
output <<= 3;
|
||||
output += self().data_at(6);
|
||||
output <<= 3;
|
||||
output += self().data_at(7);
|
||||
output <<= 3;
|
||||
output += self().data_at(8);
|
||||
output <<= 3;
|
||||
output += self().data_at(9);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 2: // 6 5-bit values
|
||||
{
|
||||
unsigned int output = 0x02U << 30; // 10
|
||||
output += self().data_at(0) << 25;
|
||||
output += self().data_at(1) << 20;
|
||||
output += self().data_at(2) << 15;
|
||||
output += self().data_at(3) << 10;
|
||||
output += self().data_at(4) << 5;
|
||||
output += self().data_at(5);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 3: // 4 7-bit values
|
||||
{
|
||||
unsigned int output = 0x0CU << 28; // 1100
|
||||
output += self().data_at(0) << 21;
|
||||
output += self().data_at(1) << 14;
|
||||
output += self().data_at(2) << 7;
|
||||
output += self().data_at(3);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 4: // 3 9-bit values
|
||||
{
|
||||
unsigned int output = 0x0DU << 28; // 1101x (1 bit lost)
|
||||
output += self().data_at(0) << 18;
|
||||
output += self().data_at(1) << 9;
|
||||
output += self().data_at(2);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 5: // 2 14-bit values
|
||||
{
|
||||
unsigned int output = 0x0EU << 28; // 1110
|
||||
output += self().data_at(0) << 14;
|
||||
output += self().data_at(1);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 6: // one 28-bit value
|
||||
{
|
||||
unsigned int output = 0x0FU << 28; // 1111
|
||||
output += self().data_at(0);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
}
|
||||
self().forward(max_count[id]);
|
||||
size_ -= max_count[id];
|
||||
}
|
||||
unsigned int output = 0x01 << 3; // 01
|
||||
output += self().data_at(0);
|
||||
output <<= 3;
|
||||
output += self().data_at(1);
|
||||
output <<= 3;
|
||||
output += self().data_at(2);
|
||||
output <<= 3;
|
||||
output += self().data_at(3);
|
||||
output <<= 3;
|
||||
output += self().data_at(4);
|
||||
output <<= 3;
|
||||
output += self().data_at(5);
|
||||
output <<= 3;
|
||||
output += self().data_at(6);
|
||||
output <<= 3;
|
||||
output += self().data_at(7);
|
||||
output <<= 3;
|
||||
output += self().data_at(8);
|
||||
output <<= 3;
|
||||
output += self().data_at(9);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 2: // 6 5-bit values
|
||||
{
|
||||
unsigned int output = 0x02U << 30; // 10
|
||||
output += self().data_at(0) << 25;
|
||||
output += self().data_at(1) << 20;
|
||||
output += self().data_at(2) << 15;
|
||||
output += self().data_at(3) << 10;
|
||||
output += self().data_at(4) << 5;
|
||||
output += self().data_at(5);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 3: // 4 7-bit values
|
||||
{
|
||||
unsigned int output = 0x0CU << 28; // 1100
|
||||
output += self().data_at(0) << 21;
|
||||
output += self().data_at(1) << 14;
|
||||
output += self().data_at(2) << 7;
|
||||
output += self().data_at(3);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 4: // 3 9-bit values
|
||||
{
|
||||
unsigned int output = 0x0DU << 28; // 1101x (1 bit lost)
|
||||
output += self().data_at(0) << 18;
|
||||
output += self().data_at(1) << 9;
|
||||
output += self().data_at(2);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 5: // 2 14-bit values
|
||||
{
|
||||
unsigned int output = 0x0EU << 28; // 1110
|
||||
output += self().data_at(0) << 14;
|
||||
output += self().data_at(1);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 6: // one 28-bit value
|
||||
{
|
||||
unsigned int output = 0x0FU << 28; // 1111
|
||||
output += self().data_at(0);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
}
|
||||
self().forward(max_count[id]);
|
||||
size_ -= max_count[id];
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -315,12 +315,12 @@ namespace spot
|
|||
|
||||
Self& self()
|
||||
{
|
||||
return static_cast<Self&>(*this);
|
||||
return static_cast<Self&>(*this);
|
||||
}
|
||||
|
||||
const Self& self() const
|
||||
{
|
||||
return static_cast<const Self&>(*this);
|
||||
return static_cast<const Self&>(*this);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -331,29 +331,29 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_array_array_compression(const int* array, size_t n,
|
||||
int* dest, size_t& dest_n)
|
||||
: stream_compression_base<int_array_array_compression>(n),
|
||||
array_(array), result_size_(dest_n),
|
||||
result_(dest), result_end_(dest + dest_n)
|
||||
int* dest, size_t& dest_n)
|
||||
: stream_compression_base<int_array_array_compression>(n),
|
||||
array_(array), result_size_(dest_n),
|
||||
result_(dest), result_end_(dest + dest_n)
|
||||
{
|
||||
result_size_ = 0; // this resets dest_n.
|
||||
result_size_ = 0; // this resets dest_n.
|
||||
}
|
||||
|
||||
void push_data(unsigned int i)
|
||||
{
|
||||
assert(result_ < result_end_);
|
||||
++result_size_;
|
||||
*result_++ = static_cast<int>(i);
|
||||
assert(result_ < result_end_);
|
||||
++result_size_;
|
||||
*result_++ = static_cast<int>(i);
|
||||
}
|
||||
|
||||
unsigned int data_at(size_t offset)
|
||||
{
|
||||
return static_cast<unsigned int>(array_[offset]);
|
||||
return static_cast<unsigned int>(array_[offset]);
|
||||
}
|
||||
|
||||
void forward(size_t offset)
|
||||
{
|
||||
array_ += offset;
|
||||
array_ += offset;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -368,7 +368,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_array_array_compress2(const int* array, size_t n,
|
||||
int* dest, size_t& dest_size)
|
||||
int* dest, size_t& dest_size)
|
||||
{
|
||||
int_array_array_compression c(array, n, dest, dest_size);
|
||||
c.run();
|
||||
|
|
@ -386,113 +386,113 @@ namespace spot
|
|||
|
||||
void run()
|
||||
{
|
||||
while (SPOT_LIKELY(self().have_comp_data()))
|
||||
{
|
||||
unsigned val = self().next_comp_data();
|
||||
while (SPOT_LIKELY(self().have_comp_data()))
|
||||
{
|
||||
unsigned val = self().next_comp_data();
|
||||
|
||||
unsigned id = val >> 28;
|
||||
switch (id)
|
||||
{
|
||||
case 0x00: // 00xx - 30 1-bit values.
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
self().write_data_at(0, !!(val & (1 << 29)));
|
||||
self().write_data_at(1, !!(val & (1 << 28)));
|
||||
self().write_data_at(2, !!(val & (1 << 27)));
|
||||
self().write_data_at(3, !!(val & (1 << 26)));
|
||||
self().write_data_at(4, !!(val & (1 << 25)));
|
||||
self().write_data_at(5, !!(val & (1 << 24)));
|
||||
self().write_data_at(6, !!(val & (1 << 23)));
|
||||
self().write_data_at(7, !!(val & (1 << 22)));
|
||||
self().write_data_at(8, !!(val & (1 << 21)));
|
||||
self().write_data_at(9, !!(val & (1 << 20)));
|
||||
self().write_data_at(10, !!(val & (1 << 19)));
|
||||
self().write_data_at(11, !!(val & (1 << 18)));
|
||||
self().write_data_at(12, !!(val & (1 << 17)));
|
||||
self().write_data_at(13, !!(val & (1 << 16)));
|
||||
self().write_data_at(14, !!(val & (1 << 15)));
|
||||
self().write_data_at(15, !!(val & (1 << 14)));
|
||||
self().write_data_at(16, !!(val & (1 << 13)));
|
||||
self().write_data_at(17, !!(val & (1 << 12)));
|
||||
self().write_data_at(18, !!(val & (1 << 11)));
|
||||
self().write_data_at(19, !!(val & (1 << 10)));
|
||||
self().write_data_at(20, !!(val & (1 << 9)));
|
||||
self().write_data_at(21, !!(val & (1 << 8)));
|
||||
self().write_data_at(22, !!(val & (1 << 7)));
|
||||
self().write_data_at(23, !!(val & (1 << 6)));
|
||||
self().write_data_at(24, !!(val & (1 << 5)));
|
||||
self().write_data_at(25, !!(val & (1 << 4)));
|
||||
self().write_data_at(26, !!(val & (1 << 3)));
|
||||
self().write_data_at(27, !!(val & (1 << 2)));
|
||||
self().write_data_at(28, !!(val & (1 << 1)));
|
||||
self().write_data_at(29, !!(val & (1 << 0)));
|
||||
self().forward(30);
|
||||
break;
|
||||
case 0x04: // 01xx - 10 3-bit values.
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
self().write_data_at(0, (val >> 27) & 0x07);
|
||||
self().write_data_at(1, (val >> 24) & 0x07);
|
||||
self().write_data_at(2, (val >> 21) & 0x07);
|
||||
self().write_data_at(3, (val >> 18) & 0x07);
|
||||
self().write_data_at(4, (val >> 15) & 0x07);
|
||||
self().write_data_at(5, (val >> 12) & 0x07);
|
||||
self().write_data_at(6, (val >> 9) & 0x07);
|
||||
self().write_data_at(7, (val >> 6) & 0x07);
|
||||
self().write_data_at(8, (val >> 3) & 0x07);
|
||||
self().write_data_at(9, (val >> 0) & 0x07);
|
||||
self().forward(10);
|
||||
break;
|
||||
case 0x08: // 10xx - 6 5-bit values.
|
||||
case 0x09:
|
||||
case 0x0A:
|
||||
case 0x0B:
|
||||
self().write_data_at(0, (val >> 25) & 0x1F);
|
||||
self().write_data_at(1, (val >> 20) & 0x1F);
|
||||
self().write_data_at(2, (val >> 15) & 0x1F);
|
||||
self().write_data_at(3, (val >> 10) & 0x1F);
|
||||
self().write_data_at(4, (val >> 5) & 0x1F);
|
||||
self().write_data_at(5, (val >> 0) & 0x1F);
|
||||
self().forward(6);
|
||||
break;
|
||||
case 0x0C: // 1100 - 4 7-bit values
|
||||
self().write_data_at(0, (val >> 21) & 0x7F);
|
||||
self().write_data_at(1, (val >> 14) & 0x7F);
|
||||
self().write_data_at(2, (val >> 7) & 0x7F);
|
||||
self().write_data_at(3, (val >> 0) & 0x7F);
|
||||
self().forward(4);
|
||||
break;
|
||||
case 0x0D: // 1101x - 3 9-bit values.
|
||||
self().write_data_at(0, (val >> 18) & 0x1FF);
|
||||
self().write_data_at(1, (val >> 9) & 0x1FF);
|
||||
self().write_data_at(2, (val >> 0) & 0x1FF);
|
||||
self().forward(3);
|
||||
break;
|
||||
case 0x0E: // 110x - 2 14-bit values.
|
||||
self().write_data_at(0, (val >> 14) & 0x3FFF);
|
||||
self().write_data_at(1, (val >> 0) & 0x3FFF);
|
||||
self().forward(2);
|
||||
break;
|
||||
case 0x0F: // 1100 - 1 28-bit value.
|
||||
self().write_data_at(0, val & 0xFFFFFFF);
|
||||
self().forward(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
unsigned id = val >> 28;
|
||||
switch (id)
|
||||
{
|
||||
case 0x00: // 00xx - 30 1-bit values.
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
self().write_data_at(0, !!(val & (1 << 29)));
|
||||
self().write_data_at(1, !!(val & (1 << 28)));
|
||||
self().write_data_at(2, !!(val & (1 << 27)));
|
||||
self().write_data_at(3, !!(val & (1 << 26)));
|
||||
self().write_data_at(4, !!(val & (1 << 25)));
|
||||
self().write_data_at(5, !!(val & (1 << 24)));
|
||||
self().write_data_at(6, !!(val & (1 << 23)));
|
||||
self().write_data_at(7, !!(val & (1 << 22)));
|
||||
self().write_data_at(8, !!(val & (1 << 21)));
|
||||
self().write_data_at(9, !!(val & (1 << 20)));
|
||||
self().write_data_at(10, !!(val & (1 << 19)));
|
||||
self().write_data_at(11, !!(val & (1 << 18)));
|
||||
self().write_data_at(12, !!(val & (1 << 17)));
|
||||
self().write_data_at(13, !!(val & (1 << 16)));
|
||||
self().write_data_at(14, !!(val & (1 << 15)));
|
||||
self().write_data_at(15, !!(val & (1 << 14)));
|
||||
self().write_data_at(16, !!(val & (1 << 13)));
|
||||
self().write_data_at(17, !!(val & (1 << 12)));
|
||||
self().write_data_at(18, !!(val & (1 << 11)));
|
||||
self().write_data_at(19, !!(val & (1 << 10)));
|
||||
self().write_data_at(20, !!(val & (1 << 9)));
|
||||
self().write_data_at(21, !!(val & (1 << 8)));
|
||||
self().write_data_at(22, !!(val & (1 << 7)));
|
||||
self().write_data_at(23, !!(val & (1 << 6)));
|
||||
self().write_data_at(24, !!(val & (1 << 5)));
|
||||
self().write_data_at(25, !!(val & (1 << 4)));
|
||||
self().write_data_at(26, !!(val & (1 << 3)));
|
||||
self().write_data_at(27, !!(val & (1 << 2)));
|
||||
self().write_data_at(28, !!(val & (1 << 1)));
|
||||
self().write_data_at(29, !!(val & (1 << 0)));
|
||||
self().forward(30);
|
||||
break;
|
||||
case 0x04: // 01xx - 10 3-bit values.
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
self().write_data_at(0, (val >> 27) & 0x07);
|
||||
self().write_data_at(1, (val >> 24) & 0x07);
|
||||
self().write_data_at(2, (val >> 21) & 0x07);
|
||||
self().write_data_at(3, (val >> 18) & 0x07);
|
||||
self().write_data_at(4, (val >> 15) & 0x07);
|
||||
self().write_data_at(5, (val >> 12) & 0x07);
|
||||
self().write_data_at(6, (val >> 9) & 0x07);
|
||||
self().write_data_at(7, (val >> 6) & 0x07);
|
||||
self().write_data_at(8, (val >> 3) & 0x07);
|
||||
self().write_data_at(9, (val >> 0) & 0x07);
|
||||
self().forward(10);
|
||||
break;
|
||||
case 0x08: // 10xx - 6 5-bit values.
|
||||
case 0x09:
|
||||
case 0x0A:
|
||||
case 0x0B:
|
||||
self().write_data_at(0, (val >> 25) & 0x1F);
|
||||
self().write_data_at(1, (val >> 20) & 0x1F);
|
||||
self().write_data_at(2, (val >> 15) & 0x1F);
|
||||
self().write_data_at(3, (val >> 10) & 0x1F);
|
||||
self().write_data_at(4, (val >> 5) & 0x1F);
|
||||
self().write_data_at(5, (val >> 0) & 0x1F);
|
||||
self().forward(6);
|
||||
break;
|
||||
case 0x0C: // 1100 - 4 7-bit values
|
||||
self().write_data_at(0, (val >> 21) & 0x7F);
|
||||
self().write_data_at(1, (val >> 14) & 0x7F);
|
||||
self().write_data_at(2, (val >> 7) & 0x7F);
|
||||
self().write_data_at(3, (val >> 0) & 0x7F);
|
||||
self().forward(4);
|
||||
break;
|
||||
case 0x0D: // 1101x - 3 9-bit values.
|
||||
self().write_data_at(0, (val >> 18) & 0x1FF);
|
||||
self().write_data_at(1, (val >> 9) & 0x1FF);
|
||||
self().write_data_at(2, (val >> 0) & 0x1FF);
|
||||
self().forward(3);
|
||||
break;
|
||||
case 0x0E: // 110x - 2 14-bit values.
|
||||
self().write_data_at(0, (val >> 14) & 0x3FFF);
|
||||
self().write_data_at(1, (val >> 0) & 0x3FFF);
|
||||
self().forward(2);
|
||||
break;
|
||||
case 0x0F: // 1100 - 1 28-bit value.
|
||||
self().write_data_at(0, val & 0xFFFFFFF);
|
||||
self().forward(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
Self& self()
|
||||
{
|
||||
return static_cast<Self&>(*this);
|
||||
return static_cast<Self&>(*this);
|
||||
}
|
||||
|
||||
const Self& self() const
|
||||
{
|
||||
return static_cast<const Self&>(*this);
|
||||
return static_cast<const Self&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -502,30 +502,30 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_array_array_decompression(const int* array,
|
||||
size_t array_size,
|
||||
int* res)
|
||||
: array_(array), n_(array_size), pos_(0), result_(res)
|
||||
size_t array_size,
|
||||
int* res)
|
||||
: array_(array), n_(array_size), pos_(0), result_(res)
|
||||
{
|
||||
}
|
||||
|
||||
void write_data_at(size_t pos, unsigned int i)
|
||||
{
|
||||
result_[pos] = i;
|
||||
result_[pos] = i;
|
||||
}
|
||||
|
||||
void forward(size_t i)
|
||||
{
|
||||
result_ += i;
|
||||
result_ += i;
|
||||
}
|
||||
|
||||
bool have_comp_data() const
|
||||
{
|
||||
return pos_ < n_;
|
||||
return pos_ < n_;
|
||||
}
|
||||
|
||||
unsigned int next_comp_data()
|
||||
{
|
||||
return array_[pos_++];
|
||||
return array_[pos_++];
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -540,7 +540,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_array_array_decompress2(const int* array, size_t array_size, int* res,
|
||||
size_t)
|
||||
size_t)
|
||||
{
|
||||
int_array_array_decompression c(array, array_size, res);
|
||||
c.run();
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace spot
|
|||
/// filled in \a dest
|
||||
SPOT_API void
|
||||
int_array_array_compress2(const int* array, size_t n,
|
||||
int* dest, size_t& dest_size);
|
||||
int* dest, size_t& dest_size);
|
||||
|
||||
/// \brief Uncompress an int array of size \a array_size into a int
|
||||
/// array of size \a size.
|
||||
|
|
@ -44,7 +44,7 @@ namespace spot
|
|||
/// \a size must be the exact expected size of uncompressed array.
|
||||
SPOT_API void
|
||||
int_array_array_decompress2(const int* array, size_t array_size,
|
||||
int* res, size_t size);
|
||||
int* res, size_t size);
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,129 +55,129 @@ namespace spot
|
|||
|
||||
public:
|
||||
stream_compression_base()
|
||||
: cur_(0), bits_left_(max_bits)
|
||||
: cur_(0), bits_left_(max_bits)
|
||||
{
|
||||
}
|
||||
|
||||
void emit(unsigned int val)
|
||||
{
|
||||
if (val == 0)
|
||||
{
|
||||
self().push_bits(0x0, 2, 0x3);
|
||||
}
|
||||
else if (val == 1)
|
||||
{
|
||||
self().push_bits(0x2, 3, 0x7);
|
||||
}
|
||||
else if (val >= 2 && val <= 5)
|
||||
{
|
||||
self().push_bits(0x3, 3, 0x7);
|
||||
self().push_bits(val - 2, 2, 0x3);
|
||||
}
|
||||
else if (val >= 6 && val <= 22)
|
||||
{
|
||||
self().push_bits(0x4, 3, 0x7);
|
||||
self().push_bits(val - 6, 4, 0xf);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(val > 22);
|
||||
self().push_bits(0x7, 3, 0x7);
|
||||
self().push_bits(val, 32, -1U);
|
||||
}
|
||||
if (val == 0)
|
||||
{
|
||||
self().push_bits(0x0, 2, 0x3);
|
||||
}
|
||||
else if (val == 1)
|
||||
{
|
||||
self().push_bits(0x2, 3, 0x7);
|
||||
}
|
||||
else if (val >= 2 && val <= 5)
|
||||
{
|
||||
self().push_bits(0x3, 3, 0x7);
|
||||
self().push_bits(val - 2, 2, 0x3);
|
||||
}
|
||||
else if (val >= 6 && val <= 22)
|
||||
{
|
||||
self().push_bits(0x4, 3, 0x7);
|
||||
self().push_bits(val - 6, 4, 0xf);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(val > 22);
|
||||
self().push_bits(0x7, 3, 0x7);
|
||||
self().push_bits(val, 32, -1U);
|
||||
}
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
unsigned int last_val = 0;
|
||||
unsigned int last_val = 0;
|
||||
|
||||
while (SPOT_LIKELY(self().have_data()))
|
||||
{
|
||||
unsigned int val = self().next_data();
|
||||
// Repeated value? Try to find more.
|
||||
if (val == last_val)
|
||||
{
|
||||
unsigned int count = 1;
|
||||
while (count < 40 && self().skip_if(val))
|
||||
++count;
|
||||
while (SPOT_LIKELY(self().have_data()))
|
||||
{
|
||||
unsigned int val = self().next_data();
|
||||
// Repeated value? Try to find more.
|
||||
if (val == last_val)
|
||||
{
|
||||
unsigned int count = 1;
|
||||
while (count < 40 && self().skip_if(val))
|
||||
++count;
|
||||
|
||||
if ((val == 0 && count < 3) || (val == 1 && count == 1))
|
||||
{
|
||||
// it is more efficient to emit 0 once or twice directly
|
||||
// (e.g., 00 00 vs. 011 11)
|
||||
// for value 1, repetition is worthwhile for count > 1
|
||||
// (e.g., 010 010 vs. 011 00)
|
||||
while (count--)
|
||||
emit(val);
|
||||
}
|
||||
else if (count < 9)
|
||||
{
|
||||
self().push_bits(0x5, 3, 0x7);
|
||||
self().push_bits(count - 1, 3, 0x7);
|
||||
}
|
||||
else
|
||||
{
|
||||
self().push_bits(0x6, 3, 0x7);
|
||||
self().push_bits(count - 9, 5, 0x1f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
emit(val);
|
||||
last_val = val;
|
||||
}
|
||||
}
|
||||
flush();
|
||||
if ((val == 0 && count < 3) || (val == 1 && count == 1))
|
||||
{
|
||||
// it is more efficient to emit 0 once or twice directly
|
||||
// (e.g., 00 00 vs. 011 11)
|
||||
// for value 1, repetition is worthwhile for count > 1
|
||||
// (e.g., 010 010 vs. 011 00)
|
||||
while (count--)
|
||||
emit(val);
|
||||
}
|
||||
else if (count < 9)
|
||||
{
|
||||
self().push_bits(0x5, 3, 0x7);
|
||||
self().push_bits(count - 1, 3, 0x7);
|
||||
}
|
||||
else
|
||||
{
|
||||
self().push_bits(0x6, 3, 0x7);
|
||||
self().push_bits(count - 9, 5, 0x1f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
emit(val);
|
||||
last_val = val;
|
||||
}
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
// This version assumes there is at least n bits free in cur_.
|
||||
void
|
||||
push_bits_unchecked(unsigned int bits, unsigned int n, unsigned int mask)
|
||||
{
|
||||
cur_ <<= n;
|
||||
cur_ |= (bits & mask);
|
||||
if (SPOT_LIKELY(bits_left_ -= n))
|
||||
return;
|
||||
cur_ <<= n;
|
||||
cur_ |= (bits & mask);
|
||||
if (SPOT_LIKELY(bits_left_ -= n))
|
||||
return;
|
||||
|
||||
self().push_data(cur_);
|
||||
cur_ = 0;
|
||||
bits_left_ = max_bits;
|
||||
self().push_data(cur_);
|
||||
cur_ = 0;
|
||||
bits_left_ = max_bits;
|
||||
}
|
||||
|
||||
void
|
||||
push_bits(unsigned int bits, unsigned int n, unsigned int mask)
|
||||
{
|
||||
if (SPOT_LIKELY(n <= bits_left_))
|
||||
{
|
||||
push_bits_unchecked(bits, n, mask);
|
||||
return;
|
||||
}
|
||||
if (SPOT_LIKELY(n <= bits_left_))
|
||||
{
|
||||
push_bits_unchecked(bits, n, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
// bits_left_ < n
|
||||
// bits_left_ < n
|
||||
|
||||
unsigned int right_bit_count = n - bits_left_;
|
||||
unsigned int left = bits >> right_bit_count;
|
||||
push_bits_unchecked(left, bits_left_, (1 << bits_left_) - 1);
|
||||
push_bits_unchecked(bits, right_bit_count, (1 << right_bit_count) - 1);
|
||||
unsigned int right_bit_count = n - bits_left_;
|
||||
unsigned int left = bits >> right_bit_count;
|
||||
push_bits_unchecked(left, bits_left_, (1 << bits_left_) - 1);
|
||||
push_bits_unchecked(bits, right_bit_count, (1 << right_bit_count) - 1);
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
if (bits_left_ == max_bits)
|
||||
return;
|
||||
cur_ <<= bits_left_;
|
||||
self().push_data(cur_);
|
||||
if (bits_left_ == max_bits)
|
||||
return;
|
||||
cur_ <<= bits_left_;
|
||||
self().push_data(cur_);
|
||||
}
|
||||
|
||||
protected:
|
||||
Self& self()
|
||||
{
|
||||
return static_cast<Self&>(*this);
|
||||
return static_cast<Self&>(*this);
|
||||
}
|
||||
|
||||
const Self& self() const
|
||||
{
|
||||
return static_cast<const Self&>(*this);
|
||||
return static_cast<const Self&>(*this);
|
||||
}
|
||||
|
||||
unsigned int cur_;
|
||||
|
|
@ -189,41 +189,41 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_array_vector_compression(const int* array, size_t n)
|
||||
: array_(array), n_(n), pos_(0), result_(new std::vector<unsigned int>)
|
||||
: array_(array), n_(n), pos_(0), result_(new std::vector<unsigned int>)
|
||||
{
|
||||
}
|
||||
|
||||
void push_data(unsigned int i)
|
||||
{
|
||||
result_->push_back(i);
|
||||
result_->push_back(i);
|
||||
}
|
||||
|
||||
const std::vector<unsigned int>*
|
||||
result() const
|
||||
{
|
||||
return result_;
|
||||
return result_;
|
||||
}
|
||||
|
||||
bool have_data() const
|
||||
{
|
||||
return pos_ < n_;
|
||||
return pos_ < n_;
|
||||
}
|
||||
|
||||
unsigned int next_data()
|
||||
{
|
||||
return static_cast<unsigned int>(array_[pos_++]);
|
||||
return static_cast<unsigned int>(array_[pos_++]);
|
||||
}
|
||||
|
||||
bool skip_if(unsigned int val)
|
||||
{
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
|
||||
if (static_cast<unsigned int>(array_[pos_]) != val)
|
||||
return false;
|
||||
if (static_cast<unsigned int>(array_[pos_]) != val)
|
||||
return false;
|
||||
|
||||
++pos_;
|
||||
return true;
|
||||
++pos_;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -238,36 +238,36 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_vector_vector_compression(const std::vector<int>& input,
|
||||
std::vector<unsigned int>& output)
|
||||
: input_(input), pos_(input.begin()), end_(input.end()), output_(output)
|
||||
std::vector<unsigned int>& output)
|
||||
: input_(input), pos_(input.begin()), end_(input.end()), output_(output)
|
||||
{
|
||||
}
|
||||
|
||||
void push_data(unsigned int i)
|
||||
{
|
||||
output_.push_back(i);
|
||||
output_.push_back(i);
|
||||
}
|
||||
|
||||
bool have_data() const
|
||||
{
|
||||
return pos_ < end_;
|
||||
return pos_ < end_;
|
||||
}
|
||||
|
||||
unsigned int next_data()
|
||||
{
|
||||
return static_cast<unsigned int>(*pos_++);
|
||||
return static_cast<unsigned int>(*pos_++);
|
||||
}
|
||||
|
||||
bool skip_if(unsigned int val)
|
||||
{
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
|
||||
if (static_cast<unsigned int>(*pos_) != val)
|
||||
return false;
|
||||
if (static_cast<unsigned int>(*pos_) != val)
|
||||
return false;
|
||||
|
||||
++pos_;
|
||||
return true;
|
||||
++pos_;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -282,40 +282,40 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_array_array_compression(const int* array, size_t n,
|
||||
int* dest, size_t& dest_n)
|
||||
: array_(array), n_(n), pos_(0),
|
||||
result_size_(dest_n), result_(dest), result_end_(dest + dest_n)
|
||||
int* dest, size_t& dest_n)
|
||||
: array_(array), n_(n), pos_(0),
|
||||
result_size_(dest_n), result_(dest), result_end_(dest + dest_n)
|
||||
{
|
||||
result_size_ = 0; // this resets dest_n.
|
||||
result_size_ = 0; // this resets dest_n.
|
||||
}
|
||||
|
||||
void push_data(unsigned int i)
|
||||
{
|
||||
assert(result_ < result_end_);
|
||||
++result_size_;
|
||||
*result_++ = static_cast<int>(i);
|
||||
assert(result_ < result_end_);
|
||||
++result_size_;
|
||||
*result_++ = static_cast<int>(i);
|
||||
}
|
||||
|
||||
bool have_data() const
|
||||
{
|
||||
return pos_ < n_;
|
||||
return pos_ < n_;
|
||||
}
|
||||
|
||||
unsigned int next_data()
|
||||
{
|
||||
return static_cast<unsigned int>(array_[pos_++]);
|
||||
return static_cast<unsigned int>(array_[pos_++]);
|
||||
}
|
||||
|
||||
bool skip_if(unsigned int val)
|
||||
{
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
|
||||
if (static_cast<unsigned int>(array_[pos_]) != val)
|
||||
return false;
|
||||
if (static_cast<unsigned int>(array_[pos_]) != val)
|
||||
return false;
|
||||
|
||||
++pos_;
|
||||
return true;
|
||||
++pos_;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -330,7 +330,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_vector_vector_compress(const std::vector<int>& input,
|
||||
std::vector<unsigned>& output)
|
||||
std::vector<unsigned>& output)
|
||||
{
|
||||
int_vector_vector_compression c(input, output);
|
||||
c.run();
|
||||
|
|
@ -346,7 +346,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_array_array_compress(const int* array, size_t n,
|
||||
int* dest, size_t& dest_size)
|
||||
int* dest, size_t& dest_size)
|
||||
{
|
||||
int_array_array_compression c(array, n, dest, dest_size);
|
||||
c.run();
|
||||
|
|
@ -365,154 +365,154 @@ namespace spot
|
|||
public:
|
||||
void refill()
|
||||
{
|
||||
if (SPOT_UNLIKELY(look_bits_ == 0))
|
||||
{
|
||||
look_bits_ = max_bits;
|
||||
look_ = buffer_;
|
||||
if (SPOT_UNLIKELY(look_bits_ == 0))
|
||||
{
|
||||
look_bits_ = max_bits;
|
||||
look_ = buffer_;
|
||||
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
buffer_ = self().next_comp_data();
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
buffer_ = self().next_comp_data();
|
||||
|
||||
if (SPOT_LIKELY(buffer_bits_ != max_bits))
|
||||
{
|
||||
unsigned int fill_size = max_bits - buffer_bits_;
|
||||
look_ <<= fill_size;
|
||||
look_ |= buffer_ >> buffer_bits_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int fill_size = max_bits - look_bits_;
|
||||
if (fill_size > buffer_bits_)
|
||||
fill_size = buffer_bits_;
|
||||
if (SPOT_LIKELY(buffer_bits_ != max_bits))
|
||||
{
|
||||
unsigned int fill_size = max_bits - buffer_bits_;
|
||||
look_ <<= fill_size;
|
||||
look_ |= buffer_ >> buffer_bits_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int fill_size = max_bits - look_bits_;
|
||||
if (fill_size > buffer_bits_)
|
||||
fill_size = buffer_bits_;
|
||||
|
||||
look_ <<= fill_size;
|
||||
buffer_bits_ -= fill_size;
|
||||
look_ |= (buffer_ >> buffer_bits_) & ((1 << fill_size) - 1);
|
||||
look_bits_ += fill_size;
|
||||
look_ <<= fill_size;
|
||||
buffer_bits_ -= fill_size;
|
||||
look_ |= (buffer_ >> buffer_bits_) & ((1 << fill_size) - 1);
|
||||
look_bits_ += fill_size;
|
||||
|
||||
if (buffer_bits_ == 0)
|
||||
{
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
buffer_ = self().next_comp_data();
|
||||
if (buffer_bits_ == 0)
|
||||
{
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
buffer_ = self().next_comp_data();
|
||||
|
||||
unsigned int left = max_bits - look_bits_;
|
||||
if (left != 0)
|
||||
{
|
||||
look_ <<= left;
|
||||
look_ |= buffer_ >> look_bits_;
|
||||
buffer_bits_ = look_bits_;
|
||||
look_bits_ = max_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_bits_ = max_bits;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int left = max_bits - look_bits_;
|
||||
if (left != 0)
|
||||
{
|
||||
look_ <<= left;
|
||||
look_ |= buffer_ >> look_bits_;
|
||||
buffer_bits_ = look_bits_;
|
||||
look_bits_ = max_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_bits_ = max_bits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int look_n_bits(unsigned int n)
|
||||
{
|
||||
if (SPOT_UNLIKELY(look_bits_ < n))
|
||||
refill();
|
||||
assert(n <= look_bits_);
|
||||
return (look_ >> (look_bits_ - n)) & ((1 << n) - 1);
|
||||
if (SPOT_UNLIKELY(look_bits_ < n))
|
||||
refill();
|
||||
assert(n <= look_bits_);
|
||||
return (look_ >> (look_bits_ - n)) & ((1 << n) - 1);
|
||||
}
|
||||
|
||||
void skip_n_bits(unsigned int n)
|
||||
{
|
||||
assert (n <= look_bits_);
|
||||
look_bits_ -= n;
|
||||
assert (n <= look_bits_);
|
||||
look_bits_ -= n;
|
||||
}
|
||||
|
||||
unsigned int get_n_bits(unsigned int n)
|
||||
{
|
||||
if (SPOT_UNLIKELY(look_bits_ < n))
|
||||
refill();
|
||||
look_bits_ -= n;
|
||||
return (look_ >> look_bits_) & ((1 << n) - 1);
|
||||
if (SPOT_UNLIKELY(look_bits_ < n))
|
||||
refill();
|
||||
look_bits_ -= n;
|
||||
return (look_ >> look_bits_) & ((1 << n) - 1);
|
||||
}
|
||||
|
||||
unsigned int get_32_bits()
|
||||
{
|
||||
// std::cerr << "get_32" << std::endl;
|
||||
if (SPOT_LIKELY(look_bits_ < 32))
|
||||
refill();
|
||||
unsigned int val = look_;
|
||||
look_bits_ = 0;
|
||||
refill();
|
||||
return val;
|
||||
// std::cerr << "get_32" << std::endl;
|
||||
if (SPOT_LIKELY(look_bits_ < 32))
|
||||
refill();
|
||||
unsigned int val = look_;
|
||||
look_bits_ = 0;
|
||||
refill();
|
||||
return val;
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
if (SPOT_UNLIKELY(!self().have_comp_data()))
|
||||
return;
|
||||
if (SPOT_UNLIKELY(!self().have_comp_data()))
|
||||
return;
|
||||
|
||||
look_ = self().next_comp_data();
|
||||
look_bits_ = max_bits;
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
{
|
||||
buffer_ = self().next_comp_data();
|
||||
buffer_bits_ = max_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_ = 0;
|
||||
buffer_bits_ = 0;
|
||||
}
|
||||
look_ = self().next_comp_data();
|
||||
look_bits_ = max_bits;
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
{
|
||||
buffer_ = self().next_comp_data();
|
||||
buffer_bits_ = max_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_ = 0;
|
||||
buffer_bits_ = 0;
|
||||
}
|
||||
|
||||
while (SPOT_LIKELY(!self().complete()))
|
||||
{
|
||||
unsigned int token = look_n_bits(3);
|
||||
switch (token)
|
||||
{
|
||||
case 0x0: // 00[0]
|
||||
case 0x1: // 00[1]
|
||||
skip_n_bits(2);
|
||||
self().push_data(0);
|
||||
break;
|
||||
case 0x2: // 010
|
||||
skip_n_bits(3);
|
||||
self().push_data(1);
|
||||
break;
|
||||
case 0x3: // 011
|
||||
skip_n_bits(3);
|
||||
self().push_data(2 + get_n_bits(2));
|
||||
break;
|
||||
case 0x4: // 100
|
||||
skip_n_bits(3);
|
||||
self().push_data(6 + get_n_bits(4));
|
||||
break;
|
||||
case 0x5: // 101
|
||||
skip_n_bits(3);
|
||||
self().repeat(1 + get_n_bits(3));
|
||||
break;
|
||||
case 0x6: // 110
|
||||
skip_n_bits(3);
|
||||
self().repeat(9 + get_n_bits(5));
|
||||
break;
|
||||
case 0x7: // 111
|
||||
skip_n_bits(3);
|
||||
self().push_data(get_32_bits());
|
||||
break;
|
||||
default:
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
while (SPOT_LIKELY(!self().complete()))
|
||||
{
|
||||
unsigned int token = look_n_bits(3);
|
||||
switch (token)
|
||||
{
|
||||
case 0x0: // 00[0]
|
||||
case 0x1: // 00[1]
|
||||
skip_n_bits(2);
|
||||
self().push_data(0);
|
||||
break;
|
||||
case 0x2: // 010
|
||||
skip_n_bits(3);
|
||||
self().push_data(1);
|
||||
break;
|
||||
case 0x3: // 011
|
||||
skip_n_bits(3);
|
||||
self().push_data(2 + get_n_bits(2));
|
||||
break;
|
||||
case 0x4: // 100
|
||||
skip_n_bits(3);
|
||||
self().push_data(6 + get_n_bits(4));
|
||||
break;
|
||||
case 0x5: // 101
|
||||
skip_n_bits(3);
|
||||
self().repeat(1 + get_n_bits(3));
|
||||
break;
|
||||
case 0x6: // 110
|
||||
skip_n_bits(3);
|
||||
self().repeat(9 + get_n_bits(5));
|
||||
break;
|
||||
case 0x7: // 111
|
||||
skip_n_bits(3);
|
||||
self().push_data(get_32_bits());
|
||||
break;
|
||||
default:
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
Self& self()
|
||||
{
|
||||
return static_cast<Self&>(*this);
|
||||
return static_cast<Self&>(*this);
|
||||
}
|
||||
|
||||
const Self& self() const
|
||||
{
|
||||
return static_cast<const Self&>(*this);
|
||||
return static_cast<const Self&>(*this);
|
||||
}
|
||||
|
||||
unsigned int look_;
|
||||
|
|
@ -526,41 +526,41 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_vector_vector_decompression(const std::vector<unsigned int>& array,
|
||||
std::vector<int>& res, size_t size)
|
||||
: prev_(0), array_(array),
|
||||
pos_(array.begin()), end_(array.end()),
|
||||
result_(res), size_(size)
|
||||
std::vector<int>& res, size_t size)
|
||||
: prev_(0), array_(array),
|
||||
pos_(array.begin()), end_(array.end()),
|
||||
result_(res), size_(size)
|
||||
{
|
||||
result_.reserve(size);
|
||||
result_.reserve(size);
|
||||
}
|
||||
|
||||
bool complete() const
|
||||
{
|
||||
return size_ == 0;
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
void push_data(int i)
|
||||
{
|
||||
prev_ = i;
|
||||
result_.push_back(i);
|
||||
--size_;
|
||||
prev_ = i;
|
||||
result_.push_back(i);
|
||||
--size_;
|
||||
}
|
||||
|
||||
void repeat(unsigned int i)
|
||||
{
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
result_.push_back(prev_);
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
result_.push_back(prev_);
|
||||
}
|
||||
|
||||
bool have_comp_data() const
|
||||
{
|
||||
return pos_ != end_;
|
||||
return pos_ != end_;
|
||||
}
|
||||
|
||||
unsigned int next_comp_data()
|
||||
{
|
||||
return *pos_++;
|
||||
return *pos_++;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -577,40 +577,40 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_vector_array_decompression(const std::vector<unsigned int>* array,
|
||||
int* res,
|
||||
size_t size)
|
||||
: prev_(0), array_(array), n_(array->size()), pos_(0), result_(res),
|
||||
size_(size)
|
||||
int* res,
|
||||
size_t size)
|
||||
: prev_(0), array_(array), n_(array->size()), pos_(0), result_(res),
|
||||
size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
bool complete() const
|
||||
{
|
||||
return size_ == 0;
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
void push_data(int i)
|
||||
{
|
||||
prev_ = i;
|
||||
*result_++ = i;
|
||||
--size_;
|
||||
prev_ = i;
|
||||
*result_++ = i;
|
||||
--size_;
|
||||
}
|
||||
|
||||
void repeat(unsigned int i)
|
||||
{
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
*result_++ = prev_;
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
*result_++ = prev_;
|
||||
}
|
||||
|
||||
bool have_comp_data() const
|
||||
{
|
||||
return pos_ < n_;
|
||||
return pos_ < n_;
|
||||
}
|
||||
|
||||
unsigned int next_comp_data()
|
||||
{
|
||||
return (*array_)[pos_++];
|
||||
return (*array_)[pos_++];
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -627,41 +627,41 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_array_array_decompression(const int* array,
|
||||
size_t array_size,
|
||||
int* res,
|
||||
size_t size)
|
||||
: prev_(0), array_(array), n_(array_size), pos_(0), result_(res),
|
||||
size_(size)
|
||||
size_t array_size,
|
||||
int* res,
|
||||
size_t size)
|
||||
: prev_(0), array_(array), n_(array_size), pos_(0), result_(res),
|
||||
size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
bool complete() const
|
||||
{
|
||||
return size_ == 0;
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
void push_data(int i)
|
||||
{
|
||||
prev_ = i;
|
||||
*result_++ = i;
|
||||
--size_;
|
||||
prev_ = i;
|
||||
*result_++ = i;
|
||||
--size_;
|
||||
}
|
||||
|
||||
void repeat(unsigned int i)
|
||||
{
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
*result_++ = prev_;
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
*result_++ = prev_;
|
||||
}
|
||||
|
||||
bool have_comp_data() const
|
||||
{
|
||||
return pos_ < n_;
|
||||
return pos_ < n_;
|
||||
}
|
||||
|
||||
unsigned int next_comp_data()
|
||||
{
|
||||
return array_[pos_++];
|
||||
return array_[pos_++];
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -677,7 +677,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_vector_vector_decompress(const std::vector<unsigned int>& input,
|
||||
std::vector<int>& output, size_t size)
|
||||
std::vector<int>& output, size_t size)
|
||||
{
|
||||
int_vector_vector_decompression c(input, output, size);
|
||||
c.run();
|
||||
|
|
@ -685,7 +685,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_vector_array_decompress(const std::vector<unsigned int>* array, int* res,
|
||||
size_t size)
|
||||
size_t size)
|
||||
{
|
||||
int_vector_array_decompression c(array, res, size);
|
||||
c.run();
|
||||
|
|
@ -693,7 +693,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_array_array_decompress(const int* array, size_t array_size,
|
||||
int* res, size_t size)
|
||||
int* res, size_t size)
|
||||
{
|
||||
int_array_array_decompression c(array, array_size, res, size);
|
||||
c.run();
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace spot
|
|||
/// Compress an int vector into a vector of unsigned int.
|
||||
SPOT_API void
|
||||
int_vector_vector_compress(const std::vector<int>& input,
|
||||
std::vector<unsigned int>& output);
|
||||
std::vector<unsigned int>& output);
|
||||
|
||||
/// \brief Uncompress a vector of unsigned int into a vector of
|
||||
/// size \a size.
|
||||
|
|
@ -39,7 +39,7 @@ namespace spot
|
|||
/// \a size must be the exact expected size of uncompressed array.
|
||||
SPOT_API void
|
||||
int_vector_vector_decompress(const std::vector<unsigned int>& array,
|
||||
std::vector<int>& output, size_t size);
|
||||
std::vector<int>& output, size_t size);
|
||||
|
||||
/// Compress an int array if size \a n into a vector of unsigned int.
|
||||
SPOT_API const std::vector<unsigned int>*
|
||||
|
|
@ -51,7 +51,7 @@ namespace spot
|
|||
/// \a size must be the exact expected size of uncompressed array.
|
||||
SPOT_API void
|
||||
int_vector_array_decompress(const std::vector<unsigned int>* array,
|
||||
int* res, size_t size);
|
||||
int* res, size_t size);
|
||||
|
||||
/// \brief Compress an int array of size \a n into a int array.
|
||||
///
|
||||
|
|
@ -61,7 +61,7 @@ namespace spot
|
|||
/// filled in \a dest
|
||||
SPOT_API void
|
||||
int_array_array_compress(const int* array, size_t n,
|
||||
int* dest, size_t& dest_size);
|
||||
int* dest, size_t& dest_size);
|
||||
|
||||
/// \brief Uncompress an int array of size \a array_size into a int
|
||||
/// array of size \a size.
|
||||
|
|
@ -69,7 +69,7 @@ namespace spot
|
|||
/// \a size must be the exact expected size of uncompressed array.
|
||||
SPOT_API void
|
||||
int_array_array_decompress(const int* array, size_t array_size,
|
||||
int* res, size_t size);
|
||||
int* res, size_t size);
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,8 +157,8 @@ namespace spot
|
|||
position last = loc.end - 1;
|
||||
ostr << loc.begin;
|
||||
if (last.filename
|
||||
&& (!loc.begin.filename
|
||||
|| *loc.begin.filename != *last.filename))
|
||||
&& (!loc.begin.filename
|
||||
|| *loc.begin.filename != *last.filename))
|
||||
ostr << '-' << last;
|
||||
else if (loc.begin.line != last.line)
|
||||
ostr << '-' << last.line << '.' << last.column;
|
||||
|
|
|
|||
|
|
@ -51,12 +51,12 @@ namespace spot
|
|||
{
|
||||
if (input_min == input_max)
|
||||
{
|
||||
cube_.push(bdd_satprefix(input_min));
|
||||
input_max = input_min;
|
||||
cube_.push(bdd_satprefix(input_min));
|
||||
input_max = input_min;
|
||||
}
|
||||
else
|
||||
{
|
||||
cube_.push(bddtrue);
|
||||
cube_.push(bddtrue);
|
||||
}
|
||||
bdd common = input_min & input_max;
|
||||
todo_.emplace(input_min, input_max, bdd_support(common));
|
||||
|
|
@ -67,110 +67,110 @@ namespace spot
|
|||
{
|
||||
while (!todo_.empty())
|
||||
{
|
||||
local_vars& l = todo_.top();
|
||||
switch (l.step)
|
||||
{
|
||||
case local_vars::FirstStep:
|
||||
next_var:
|
||||
{
|
||||
if (l.f_min == bddfalse)
|
||||
{
|
||||
ret_ = bddfalse;
|
||||
todo_.pop();
|
||||
continue;
|
||||
}
|
||||
if (l.vars == bddtrue || l.f_max == bddtrue)
|
||||
{
|
||||
ret_ = l.f_max;
|
||||
todo_.pop();
|
||||
return cube_.top() & ret_;
|
||||
}
|
||||
assert(l.vars != bddfalse);
|
||||
local_vars& l = todo_.top();
|
||||
switch (l.step)
|
||||
{
|
||||
case local_vars::FirstStep:
|
||||
next_var:
|
||||
{
|
||||
if (l.f_min == bddfalse)
|
||||
{
|
||||
ret_ = bddfalse;
|
||||
todo_.pop();
|
||||
continue;
|
||||
}
|
||||
if (l.vars == bddtrue || l.f_max == bddtrue)
|
||||
{
|
||||
ret_ = l.f_max;
|
||||
todo_.pop();
|
||||
return cube_.top() & ret_;
|
||||
}
|
||||
assert(l.vars != bddfalse);
|
||||
|
||||
// Pick the first variable in VARS that is used by F_MIN
|
||||
// or F_MAX. We know that VARS, F_MIN or F_MAX are not
|
||||
// constants (bddtrue or bddfalse) because one of the
|
||||
// two above `if' would have matched; so it's ok to call
|
||||
// bdd_var().
|
||||
int v = bdd_var(l.vars);
|
||||
l.vars = bdd_high(l.vars);
|
||||
int v_min = bdd_var(l.f_min);
|
||||
int v_max = bdd_var(l.f_max);
|
||||
if (v < v_min && v < v_max)
|
||||
// Do not use a while() for this goto, because we want
|
||||
// `continue' to be relative to the outermost while().
|
||||
goto next_var;
|
||||
// Pick the first variable in VARS that is used by F_MIN
|
||||
// or F_MAX. We know that VARS, F_MIN or F_MAX are not
|
||||
// constants (bddtrue or bddfalse) because one of the
|
||||
// two above `if' would have matched; so it's ok to call
|
||||
// bdd_var().
|
||||
int v = bdd_var(l.vars);
|
||||
l.vars = bdd_high(l.vars);
|
||||
int v_min = bdd_var(l.f_min);
|
||||
int v_max = bdd_var(l.f_max);
|
||||
if (v < v_min && v < v_max)
|
||||
// Do not use a while() for this goto, because we want
|
||||
// `continue' to be relative to the outermost while().
|
||||
goto next_var;
|
||||
|
||||
l.step = local_vars::SecondStep;
|
||||
l.step = local_vars::SecondStep;
|
||||
|
||||
bdd v0 = bdd_nithvar(v);
|
||||
l.v1 = bdd_ithvar(v);
|
||||
bdd v0 = bdd_nithvar(v);
|
||||
l.v1 = bdd_ithvar(v);
|
||||
|
||||
// All the following should be equivalent to
|
||||
// f0_min = bdd_restrict(f_min, v0);
|
||||
// f0_max = bdd_restrict(f_max, v0);
|
||||
// f1_min = bdd_restrict(f_min, v1);
|
||||
// f1_max = bdd_restrict(f_max, v1);
|
||||
// but we try to avoid bdd_restrict when possible.
|
||||
if (v == v_min)
|
||||
{
|
||||
l.f0_min = bdd_low(l.f_min);
|
||||
l.f1_min = bdd_high(l.f_min);
|
||||
}
|
||||
else if (v_min < v)
|
||||
{
|
||||
l.f0_min = bdd_restrict(l.f_min, v0);
|
||||
l.f1_min = bdd_restrict(l.f_min, l.v1);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.f1_min = l.f0_min = l.f_min;
|
||||
}
|
||||
if (v == v_max)
|
||||
{
|
||||
l.f0_max = bdd_low(l.f_max);
|
||||
l.f1_max = bdd_high(l.f_max);
|
||||
}
|
||||
else if (v_max < v)
|
||||
{
|
||||
l.f0_max = bdd_restrict(l.f_max, v0);
|
||||
l.f1_max = bdd_restrict(l.f_max, l.v1);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.f1_max = l.f0_max = l.f_max;
|
||||
}
|
||||
// All the following should be equivalent to
|
||||
// f0_min = bdd_restrict(f_min, v0);
|
||||
// f0_max = bdd_restrict(f_max, v0);
|
||||
// f1_min = bdd_restrict(f_min, v1);
|
||||
// f1_max = bdd_restrict(f_max, v1);
|
||||
// but we try to avoid bdd_restrict when possible.
|
||||
if (v == v_min)
|
||||
{
|
||||
l.f0_min = bdd_low(l.f_min);
|
||||
l.f1_min = bdd_high(l.f_min);
|
||||
}
|
||||
else if (v_min < v)
|
||||
{
|
||||
l.f0_min = bdd_restrict(l.f_min, v0);
|
||||
l.f1_min = bdd_restrict(l.f_min, l.v1);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.f1_min = l.f0_min = l.f_min;
|
||||
}
|
||||
if (v == v_max)
|
||||
{
|
||||
l.f0_max = bdd_low(l.f_max);
|
||||
l.f1_max = bdd_high(l.f_max);
|
||||
}
|
||||
else if (v_max < v)
|
||||
{
|
||||
l.f0_max = bdd_restrict(l.f_max, v0);
|
||||
l.f1_max = bdd_restrict(l.f_max, l.v1);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.f1_max = l.f0_max = l.f_max;
|
||||
}
|
||||
|
||||
cube_.push(cube_.top() & v0);
|
||||
todo_.emplace(l.f0_min - l.f1_max, l.f0_max, l.vars);
|
||||
}
|
||||
continue;
|
||||
cube_.push(cube_.top() & v0);
|
||||
todo_.emplace(l.f0_min - l.f1_max, l.f0_max, l.vars);
|
||||
}
|
||||
continue;
|
||||
|
||||
case local_vars::SecondStep:
|
||||
l.step = local_vars::ThirdStep;
|
||||
l.g0 = ret_;
|
||||
cube_.pop();
|
||||
cube_.push(cube_.top() & l.v1);
|
||||
todo_.emplace(l.f1_min - l.f0_max, l.f1_max, l.vars);
|
||||
continue;
|
||||
case local_vars::SecondStep:
|
||||
l.step = local_vars::ThirdStep;
|
||||
l.g0 = ret_;
|
||||
cube_.pop();
|
||||
cube_.push(cube_.top() & l.v1);
|
||||
todo_.emplace(l.f1_min - l.f0_max, l.f1_max, l.vars);
|
||||
continue;
|
||||
|
||||
case local_vars::ThirdStep:
|
||||
l.step = local_vars::FourthStep;
|
||||
l.g1 = ret_;
|
||||
cube_.pop();
|
||||
{
|
||||
bdd fs_max = l.f0_max & l.f1_max;
|
||||
bdd fs_min = fs_max & ((l.f0_min - l.g0) | (l.f1_min - l.g1));
|
||||
todo_.emplace(fs_min, fs_max, l.vars);
|
||||
}
|
||||
continue;
|
||||
case local_vars::ThirdStep:
|
||||
l.step = local_vars::FourthStep;
|
||||
l.g1 = ret_;
|
||||
cube_.pop();
|
||||
{
|
||||
bdd fs_max = l.f0_max & l.f1_max;
|
||||
bdd fs_min = fs_max & ((l.f0_min - l.g0) | (l.f1_min - l.g1));
|
||||
todo_.emplace(fs_min, fs_max, l.vars);
|
||||
}
|
||||
continue;
|
||||
|
||||
case local_vars::FourthStep:
|
||||
ret_ |= (l.g0 - l.v1) | (l.g1 & l.v1);
|
||||
todo_.pop();
|
||||
continue;
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
case local_vars::FourthStep:
|
||||
ret_ |= (l.g0 - l.v1) | (l.g1 & l.v1);
|
||||
todo_.pop();
|
||||
continue;
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
return bddfalse;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ namespace spot
|
|||
bdd f1_min, f1_max;
|
||||
bdd g0, g1;
|
||||
local_vars(bdd f_min, bdd f_max, bdd vars)
|
||||
: f_min(f_min), f_max(f_max), step(FirstStep), vars(vars) {}
|
||||
: f_min(f_min), f_max(f_max), step(FirstStep), vars(vars) {}
|
||||
};
|
||||
std::stack<local_vars> todo_;
|
||||
std::stack<bdd> cube_;
|
||||
|
|
|
|||
|
|
@ -43,17 +43,17 @@ namespace spot
|
|||
~multiple_size_pool()
|
||||
{
|
||||
while (chunklist_)
|
||||
{
|
||||
chunk_* prev = chunklist_->prev;
|
||||
free(chunklist_);
|
||||
chunklist_ = prev;
|
||||
}
|
||||
{
|
||||
chunk_* prev = chunklist_->prev;
|
||||
free(chunklist_);
|
||||
chunklist_ = prev;
|
||||
}
|
||||
}
|
||||
|
||||
size_t fixsize(size_t size) const
|
||||
{
|
||||
if (size < sizeof(block_))
|
||||
size = sizeof(block_);
|
||||
size = sizeof(block_);
|
||||
|
||||
return (size + alignment_ - 1) & ~(alignment_ - 1);
|
||||
}
|
||||
|
|
@ -67,28 +67,28 @@ namespace spot
|
|||
block_*& f = freelist_[size];
|
||||
// If we have free blocks available, return the first one.
|
||||
if (f)
|
||||
{
|
||||
block_* first = f;
|
||||
f = f->next;
|
||||
return first;
|
||||
}
|
||||
{
|
||||
block_* first = f;
|
||||
f = f->next;
|
||||
return first;
|
||||
}
|
||||
|
||||
// Else, create a block out of the last chunk of allocated
|
||||
// memory.
|
||||
|
||||
// If all the last chunk has been used, allocate one more.
|
||||
if (free_start_ + size > free_end_)
|
||||
{
|
||||
const size_t requested = (size > 128 ? size : 128) * 8192 - 64;
|
||||
chunk_* c = reinterpret_cast<chunk_*>(malloc(requested));
|
||||
if (!c)
|
||||
throw std::bad_alloc();
|
||||
c->prev = chunklist_;
|
||||
chunklist_ = c;
|
||||
{
|
||||
const size_t requested = (size > 128 ? size : 128) * 8192 - 64;
|
||||
chunk_* c = reinterpret_cast<chunk_*>(malloc(requested));
|
||||
if (!c)
|
||||
throw std::bad_alloc();
|
||||
c->prev = chunklist_;
|
||||
chunklist_ = c;
|
||||
|
||||
free_start_ = c->data_ + size;
|
||||
free_end_ = c->data_ + requested;
|
||||
}
|
||||
free_start_ = c->data_ + size;
|
||||
free_end_ = c->data_ + requested;
|
||||
}
|
||||
|
||||
void* res = free_start_;
|
||||
free_start_ += size;
|
||||
|
|
|
|||
|
|
@ -33,96 +33,96 @@ namespace spot
|
|||
{
|
||||
while (*options)
|
||||
{
|
||||
// Skip leading separators.
|
||||
while (*options && strchr(" \t\n,;", *options))
|
||||
++options;
|
||||
// Skip leading separators.
|
||||
while (*options && strchr(" \t\n,;", *options))
|
||||
++options;
|
||||
|
||||
// `!foo' is a shorthand for `foo=0'.
|
||||
const char* negated = nullptr;
|
||||
if (*options == '!')
|
||||
{
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
negated = options++;
|
||||
}
|
||||
// `!foo' is a shorthand for `foo=0'.
|
||||
const char* negated = nullptr;
|
||||
if (*options == '!')
|
||||
{
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
negated = options++;
|
||||
}
|
||||
|
||||
if (!*options)
|
||||
{
|
||||
if (negated)
|
||||
return negated;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!*options)
|
||||
{
|
||||
if (negated)
|
||||
return negated;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
const char* name_start = options;
|
||||
const char* name_start = options;
|
||||
|
||||
// Find the end of the name.
|
||||
while (*options && !strchr(", \t\n;=", *options))
|
||||
++options;
|
||||
// Find the end of the name.
|
||||
while (*options && !strchr(", \t\n;=", *options))
|
||||
++options;
|
||||
|
||||
std::string name(name_start, options);
|
||||
std::string name(name_start, options);
|
||||
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
|
||||
if (*options != '=')
|
||||
{
|
||||
options_[name] = (negated ? 0 : 1);
|
||||
}
|
||||
else if (negated)
|
||||
{
|
||||
return negated;
|
||||
}
|
||||
else
|
||||
{
|
||||
++options;
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
if (!*options)
|
||||
return name_start;
|
||||
if (*options != '=')
|
||||
{
|
||||
options_[name] = (negated ? 0 : 1);
|
||||
}
|
||||
else if (negated)
|
||||
{
|
||||
return negated;
|
||||
}
|
||||
else
|
||||
{
|
||||
++options;
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
if (!*options)
|
||||
return name_start;
|
||||
|
||||
if (*options == '\'' || *options == '"')
|
||||
{
|
||||
auto sep = *options;
|
||||
auto start = options + 1;
|
||||
do
|
||||
++options;
|
||||
while (*options && *options != sep);
|
||||
if (*options != sep)
|
||||
return start - 1;
|
||||
std::string val(start, options);
|
||||
options_str_[name] = val;
|
||||
if (*options)
|
||||
++options;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* val_end;
|
||||
int val = strtol(options, &val_end, 10);
|
||||
if (val_end == options)
|
||||
return name_start;
|
||||
if (*options == '\'' || *options == '"')
|
||||
{
|
||||
auto sep = *options;
|
||||
auto start = options + 1;
|
||||
do
|
||||
++options;
|
||||
while (*options && *options != sep);
|
||||
if (*options != sep)
|
||||
return start - 1;
|
||||
std::string val(start, options);
|
||||
options_str_[name] = val;
|
||||
if (*options)
|
||||
++options;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* val_end;
|
||||
int val = strtol(options, &val_end, 10);
|
||||
if (val_end == options)
|
||||
return name_start;
|
||||
|
||||
if (*val_end == 'K')
|
||||
{
|
||||
val *= 1024;
|
||||
++val_end;
|
||||
}
|
||||
else if (*val_end == 'M')
|
||||
{
|
||||
val *= 1024 * 1024;
|
||||
++val_end;
|
||||
}
|
||||
else if (*val_end && !strchr(" \t\n,;", *val_end))
|
||||
{
|
||||
return options;
|
||||
}
|
||||
options = val_end;
|
||||
options_[name] = val;
|
||||
}
|
||||
}
|
||||
if (*val_end == 'K')
|
||||
{
|
||||
val *= 1024;
|
||||
++val_end;
|
||||
}
|
||||
else if (*val_end == 'M')
|
||||
{
|
||||
val *= 1024 * 1024;
|
||||
++val_end;
|
||||
}
|
||||
else if (*val_end && !strchr(" \t\n,;", *val_end))
|
||||
{
|
||||
return options;
|
||||
}
|
||||
options = val_end;
|
||||
options_[name] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ namespace spot
|
|||
/// \return The previous value associated to \a option if declared,
|
||||
/// or \a def otherwise.
|
||||
std::string set_str(const char* option,
|
||||
std::string val, std::string def = {});
|
||||
std::string val, std::string def = {});
|
||||
|
||||
/// Acquire all the settings of \a o.
|
||||
void set(const option_map& o);
|
||||
|
|
|
|||
|
|
@ -96,8 +96,8 @@ namespace spot
|
|||
|
||||
if (has_next)
|
||||
{
|
||||
has_next = false;
|
||||
return next;
|
||||
has_next = false;
|
||||
return next;
|
||||
}
|
||||
|
||||
double x;
|
||||
|
|
@ -105,9 +105,9 @@ namespace spot
|
|||
double r;
|
||||
do
|
||||
{
|
||||
x = 2.0 * drand() - 1.0;
|
||||
y = 2.0 * drand() - 1.0;
|
||||
r = x * x + y * y;
|
||||
x = 2.0 * drand() - 1.0;
|
||||
y = 2.0 * drand() - 1.0;
|
||||
r = x * x + y * y;
|
||||
}
|
||||
while (r >= 1.0 || r == 0.0);
|
||||
r = sqrt(-2 * log(r) / r);
|
||||
|
|
@ -124,8 +124,8 @@ namespace spot
|
|||
|
||||
while (s < p)
|
||||
{
|
||||
s -= log(1.0 - drand());
|
||||
++x;
|
||||
s -= log(1.0 - drand());
|
||||
++x;
|
||||
}
|
||||
return x - 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,12 +97,12 @@ namespace spot
|
|||
rand() const
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
int x = round(gen() * s_ + m_);
|
||||
if (x < 0)
|
||||
continue;
|
||||
{
|
||||
int x = round(gen() * s_ + m_);
|
||||
if (x < 0)
|
||||
continue;
|
||||
if (x <= n_)
|
||||
return x;
|
||||
return x;
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
return 0;
|
||||
|
|
@ -128,11 +128,11 @@ namespace spot
|
|||
auto d = std::distance(first, last);
|
||||
if (d > 1)
|
||||
{
|
||||
for (--last; first < last; ++first, --d)
|
||||
{
|
||||
auto i = mrand(d);
|
||||
std::swap(*first, *(first + i));
|
||||
}
|
||||
for (--last; first < last; ++first, --d)
|
||||
{
|
||||
auto i = mrand(d);
|
||||
std::swap(*first, *(first + i));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// @}
|
||||
|
|
|
|||
|
|
@ -37,48 +37,48 @@ namespace spot
|
|||
|
||||
satsolver_command()
|
||||
{
|
||||
satsolver = getenv("SPOT_SATSOLVER");
|
||||
if (!satsolver)
|
||||
{
|
||||
satsolver = "glucose -verb=0 -model %I >%O";
|
||||
return;
|
||||
}
|
||||
prime(satsolver);
|
||||
if (!has('I'))
|
||||
throw std::runtime_error("SPOT_SATSOLVER should contain %I to "
|
||||
"indicate how to use the input filename.");
|
||||
if (!has('O'))
|
||||
throw std::runtime_error("SPOT_SATSOLVER should contain %O to "
|
||||
"indicate how to use the output filename.");
|
||||
satsolver = getenv("SPOT_SATSOLVER");
|
||||
if (!satsolver)
|
||||
{
|
||||
satsolver = "glucose -verb=0 -model %I >%O";
|
||||
return;
|
||||
}
|
||||
prime(satsolver);
|
||||
if (!has('I'))
|
||||
throw std::runtime_error("SPOT_SATSOLVER should contain %I to "
|
||||
"indicate how to use the input filename.");
|
||||
if (!has('O'))
|
||||
throw std::runtime_error("SPOT_SATSOLVER should contain %O to "
|
||||
"indicate how to use the output filename.");
|
||||
}
|
||||
|
||||
int
|
||||
run(printable* in, printable* out)
|
||||
{
|
||||
declare('I', in);
|
||||
declare('O', out);
|
||||
std::ostringstream s;
|
||||
format(s, satsolver);
|
||||
int res = system(s.str().c_str());
|
||||
if (res < 0 || (WIFEXITED(res) && WEXITSTATUS(res) == 127))
|
||||
{
|
||||
s << ": failed to execute";
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
// For POSIX shells, "The exit status of a command that
|
||||
// terminated because it received a signal shall be reported
|
||||
// as greater than 128."
|
||||
if (WIFEXITED(res) && WEXITSTATUS(res) >= 128)
|
||||
{
|
||||
s << ": terminated by signal";
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
if (WIFSIGNALED(res))
|
||||
{
|
||||
s << ": terminated by signal " << WTERMSIG(res);
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
return res;
|
||||
declare('I', in);
|
||||
declare('O', out);
|
||||
std::ostringstream s;
|
||||
format(s, satsolver);
|
||||
int res = system(s.str().c_str());
|
||||
if (res < 0 || (WIFEXITED(res) && WEXITSTATUS(res) == 127))
|
||||
{
|
||||
s << ": failed to execute";
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
// For POSIX shells, "The exit status of a command that
|
||||
// terminated because it received a signal shall be reported
|
||||
// as greater than 128."
|
||||
if (WIFEXITED(res) && WEXITSTATUS(res) >= 128)
|
||||
{
|
||||
s << ": terminated by signal";
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
if (WIFSIGNALED(res))
|
||||
{
|
||||
s << ": terminated by signal " << WTERMSIG(res);
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -96,25 +96,25 @@ namespace spot
|
|||
int c;
|
||||
while ((c = in->get()) != EOF)
|
||||
{
|
||||
// If a line does not start with 'v ', ignore it.
|
||||
if (c != 'v' || in->get() != ' ')
|
||||
{
|
||||
in->ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
continue;
|
||||
}
|
||||
// Otherwise, read integers one by one.
|
||||
int i;
|
||||
while (*in >> i)
|
||||
{
|
||||
if (i == 0)
|
||||
goto done;
|
||||
sol.push_back(i);
|
||||
}
|
||||
if (!in->eof())
|
||||
// If we haven't reached end-of-file, then we just attempted
|
||||
// to extract something that wasn't an integer. Clear the
|
||||
// fail bit so that will loop over.
|
||||
in->clear();
|
||||
// If a line does not start with 'v ', ignore it.
|
||||
if (c != 'v' || in->get() != ' ')
|
||||
{
|
||||
in->ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
continue;
|
||||
}
|
||||
// Otherwise, read integers one by one.
|
||||
int i;
|
||||
while (*in >> i)
|
||||
{
|
||||
if (i == 0)
|
||||
goto done;
|
||||
sol.push_back(i);
|
||||
}
|
||||
if (!in->eof())
|
||||
// If we haven't reached end-of-file, then we just attempted
|
||||
// to extract something that wasn't an integer. Clear the
|
||||
// fail bit so that will loop over.
|
||||
in->clear();
|
||||
}
|
||||
done:
|
||||
if (in != &std::cin)
|
||||
|
|
@ -149,7 +149,7 @@ namespace spot
|
|||
satsolver::solution_pair
|
||||
satsolver::get_solution()
|
||||
{
|
||||
delete cnf_stream_; // Close the file.
|
||||
delete cnf_stream_; // Close the file.
|
||||
cnf_stream_ = nullptr;
|
||||
|
||||
temporary_file* output = create_tmpfile("sat-", ".out");
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace spot
|
|||
void check() const
|
||||
{
|
||||
if (count_ < 0)
|
||||
throw std::runtime_error("too many SAT clauses (more than INT_MAX)");
|
||||
throw std::runtime_error("too many SAT clauses (more than INT_MAX)");
|
||||
}
|
||||
|
||||
clause_counter& operator++()
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ namespace spot
|
|||
time_info total;
|
||||
for (tm_type::const_iterator i = tm.begin(); i != tm.end(); ++i)
|
||||
{
|
||||
total.utime += i->second.first.utime();
|
||||
total.stime += i->second.first.stime();
|
||||
total.utime += i->second.first.utime();
|
||||
total.stime += i->second.first.stime();
|
||||
}
|
||||
clock_t grand_total = total.utime + total.stime;
|
||||
|
||||
|
|
@ -52,30 +52,30 @@ namespace spot
|
|||
<< std::endl;
|
||||
for (tm_type::const_iterator i = tm.begin(); i != tm.end(); ++i)
|
||||
{
|
||||
// truncate long keys
|
||||
std::string name = i->first;
|
||||
if (name.size() > 22)
|
||||
name.erase(22);
|
||||
// truncate long keys
|
||||
std::string name = i->first;
|
||||
if (name.size() > 22)
|
||||
name.erase(22);
|
||||
|
||||
const spot::timer& t = i->second.first;
|
||||
const char* sep = t.is_running() ? "+|" : " |";
|
||||
const spot::timer& t = i->second.first;
|
||||
const char* sep = t.is_running() ? "+|" : " |";
|
||||
|
||||
os << std::setw(22) << name << sep
|
||||
<< std::setw(6) << t.utime() << ' '
|
||||
<< std::setw(8) << (total.utime ?
|
||||
100.0 * t.utime() / total.utime : 0.)
|
||||
<< sep
|
||||
<< std::setw(6) << t.stime() << ' '
|
||||
<< std::setw(8) << (total.stime ?
|
||||
100.0 * t.stime() / total.stime : 0.)
|
||||
<< sep
|
||||
<< std::setw(6) << t.utime() + t.stime() << ' '
|
||||
<< std::setw(8) << (grand_total ?
|
||||
(100.0 * (t.utime() + t.stime()) /
|
||||
grand_total) : 0.)
|
||||
<< sep
|
||||
<< std::setw(4) << i->second.second
|
||||
<< std::endl;
|
||||
os << std::setw(22) << name << sep
|
||||
<< std::setw(6) << t.utime() << ' '
|
||||
<< std::setw(8) << (total.utime ?
|
||||
100.0 * t.utime() / total.utime : 0.)
|
||||
<< sep
|
||||
<< std::setw(6) << t.stime() << ' '
|
||||
<< std::setw(8) << (total.stime ?
|
||||
100.0 * t.stime() / total.stime : 0.)
|
||||
<< sep
|
||||
<< std::setw(6) << t.utime() + t.stime() << ' '
|
||||
<< std::setw(8) << (grand_total ?
|
||||
(100.0 * (t.utime() + t.stime()) /
|
||||
grand_total) : 0.)
|
||||
<< sep
|
||||
<< std::setw(4) << i->second.second
|
||||
<< std::endl;
|
||||
}
|
||||
os << std::setw(79) << std::setfill('-') << "" << std::setfill(' ')
|
||||
<< std::endl
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ namespace spot
|
|||
assert(i != tm.end());
|
||||
assert(0 < i->second.second);
|
||||
if (0 == --i->second.second)
|
||||
tm.erase(i);
|
||||
tm.erase(i);
|
||||
}
|
||||
|
||||
/// Return the timer \a name.
|
||||
|
|
|
|||
|
|
@ -35,14 +35,14 @@ namespace spot
|
|||
{
|
||||
const char* res = secure_getenv("SPOT_TMPDIR");
|
||||
if (res)
|
||||
return res;
|
||||
return res;
|
||||
return secure_getenv("TMPDIR");
|
||||
}
|
||||
|
||||
static int
|
||||
create_temporary_file(const char* prefix,
|
||||
const char* suffix,
|
||||
char** name)
|
||||
const char* suffix,
|
||||
char** name)
|
||||
throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
static const char* tmpdir = get_tmpdir();
|
||||
|
|
@ -51,30 +51,30 @@ namespace spot
|
|||
size_t len = strlen(prefix);
|
||||
size_t slen = 0;
|
||||
if (suffix)
|
||||
len += slen = strlen(suffix);
|
||||
len += slen = strlen(suffix);
|
||||
char* x = *name = static_cast<char*>(malloc(tmpdirlen + 1 + len + 6 + 1));
|
||||
if (!x)
|
||||
throw std::bad_alloc();
|
||||
throw std::bad_alloc();
|
||||
if (tmpdir)
|
||||
{
|
||||
x = stpcpy(x, tmpdir);
|
||||
if (x[-1] != '/')
|
||||
*x++ = '/';
|
||||
}
|
||||
{
|
||||
x = stpcpy(x, tmpdir);
|
||||
if (x[-1] != '/')
|
||||
*x++ = '/';
|
||||
}
|
||||
x = stpcpy(x, prefix);
|
||||
x = stpcpy(x, "XXXXXX");
|
||||
int fd;
|
||||
if (suffix)
|
||||
{
|
||||
stpcpy(x, suffix);
|
||||
fd = mkstemps(*name, slen);
|
||||
}
|
||||
{
|
||||
stpcpy(x, suffix);
|
||||
fd = mkstemps(*name, slen);
|
||||
}
|
||||
else
|
||||
{
|
||||
fd = mkstemp(*name);
|
||||
}
|
||||
{
|
||||
fd = mkstemp(*name);
|
||||
}
|
||||
if (fd < 0)
|
||||
throw std::runtime_error(std::string("failed to create ") + *name);
|
||||
throw std::runtime_error(std::string("failed to create ") + *name);
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,8 +113,8 @@ namespace spot
|
|||
constexpr trival operator!() const
|
||||
{
|
||||
return trival((val_ == yes_value) ? no_value :
|
||||
(val_ == no_value) ? yes_value :
|
||||
maybe_value);
|
||||
(val_ == no_value) ? yes_value :
|
||||
maybe_value);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -171,8 +171,8 @@ namespace spot
|
|||
inline std::ostream& operator<<(std::ostream& os, trival v)
|
||||
{
|
||||
return os << ((v.val() == trival::no_value) ? "no"
|
||||
: (v.val() == trival::maybe_value) ? "maybe"
|
||||
: "yes");
|
||||
: (v.val() == trival::maybe_value) ? "maybe"
|
||||
: "yes");
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ namespace spot
|
|||
spot::parse_aut_error_list::iterator it;
|
||||
for (auto& err : errors)
|
||||
{
|
||||
if (!filename.empty() && filename != "-")
|
||||
os << filename << ':';
|
||||
os << err.first << ": ";
|
||||
os << err.second << std::endl;
|
||||
printed = true;
|
||||
if (!filename.empty() && filename != "-")
|
||||
os << filename << ':';
|
||||
os << err.first << ": ";
|
||||
os << err.second << std::endl;
|
||||
printed = true;
|
||||
}
|
||||
return printed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
# define YY_DECL \
|
||||
int hoayylex(hoayy::parser::semantic_type *yylval, \
|
||||
spot::location *yylloc, \
|
||||
spot::parse_aut_error_list& error_list)
|
||||
spot::location *yylloc, \
|
||||
spot::parse_aut_error_list& error_list)
|
||||
YY_DECL;
|
||||
|
||||
namespace spot
|
||||
|
|
|
|||
|
|
@ -91,11 +91,11 @@ namespace spot
|
|||
|
||||
struct automaton_parser_options final
|
||||
{
|
||||
bool ignore_abort = false; ///< Skip aborted automata
|
||||
bool debug = false; ///< Run the parser in debug mode?
|
||||
bool trust_hoa = true; ///< Trust properties in HOA files
|
||||
bool raise_errors = false; ///< Raise errors as exceptions.
|
||||
bool want_kripke = false; ///< Parse as a Kripke structure.
|
||||
bool ignore_abort = false; ///< Skip aborted automata
|
||||
bool debug = false; ///< Run the parser in debug mode?
|
||||
bool trust_hoa = true; ///< Trust properties in HOA files
|
||||
bool raise_errors = false; ///< Raise errors as exceptions.
|
||||
bool want_kripke = false; ///< Parse as a Kripke structure.
|
||||
};
|
||||
|
||||
/// \brief Parse a stream of automata
|
||||
|
|
@ -128,7 +128,7 @@ namespace spot
|
|||
/// \param filename The file to read from.
|
||||
/// \param opts Parser options.
|
||||
automaton_stream_parser(const std::string& filename,
|
||||
automaton_parser_options opts = {});
|
||||
automaton_parser_options opts = {});
|
||||
|
||||
/// \brief Parse from an already opened file descriptor.
|
||||
///
|
||||
|
|
@ -136,7 +136,7 @@ namespace spot
|
|||
/// \param filename What to display in error messages.
|
||||
/// \param opts Parser options.
|
||||
automaton_stream_parser(int fd, const std::string& filename,
|
||||
automaton_parser_options opts = {});
|
||||
automaton_parser_options opts = {});
|
||||
|
||||
/// \brief Parse from a buffer
|
||||
///
|
||||
|
|
@ -144,8 +144,8 @@ namespace spot
|
|||
/// \param filename What to display in error messages.
|
||||
/// \param opts Parser options.
|
||||
automaton_stream_parser(const char* data,
|
||||
const std::string& filename,
|
||||
automaton_parser_options opts = {});
|
||||
const std::string& filename,
|
||||
automaton_parser_options opts = {});
|
||||
|
||||
~automaton_stream_parser();
|
||||
|
||||
|
|
@ -165,8 +165,8 @@ namespace spot
|
|||
///
|
||||
/// \warning This function is not reentrant.
|
||||
parsed_aut_ptr parse(const bdd_dict_ptr& dict,
|
||||
environment& env =
|
||||
default_environment::instance());
|
||||
environment& env =
|
||||
default_environment::instance());
|
||||
};
|
||||
|
||||
/// \brief Read the first spot::twa_graph from a file.
|
||||
|
|
@ -187,8 +187,8 @@ namespace spot
|
|||
/// \warning This function is not reentrant.
|
||||
SPOT_API parsed_aut_ptr
|
||||
parse_aut(const std::string& filename,
|
||||
const bdd_dict_ptr& dict,
|
||||
environment& env = default_environment::instance(),
|
||||
automaton_parser_options opts = {});
|
||||
const bdd_dict_ptr& dict,
|
||||
environment& env = default_environment::instance(),
|
||||
automaton_parser_options opts = {});
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace spot
|
|||
{
|
||||
void
|
||||
fix_utf8_locations(const std::string& ltl_string,
|
||||
parse_error_list& error_list)
|
||||
parse_error_list& error_list)
|
||||
{
|
||||
// LUT to convert byte positions to utf8 positions.
|
||||
// (The +2 is to account for position 0, not used,
|
||||
|
|
@ -42,15 +42,15 @@ namespace spot
|
|||
std::string::const_iterator i = b;
|
||||
std::string::const_iterator e = ltl_string.end();
|
||||
|
||||
unsigned n = 0; // number of current utf8 character
|
||||
unsigned prev = 0; // last byte of previous utf8 character
|
||||
unsigned n = 0; // number of current utf8 character
|
||||
unsigned prev = 0; // last byte of previous utf8 character
|
||||
while (i != e)
|
||||
{
|
||||
utf8::next(i, e);
|
||||
++n;
|
||||
unsigned d = std::distance(b, i);
|
||||
while (prev < d)
|
||||
b2u[++prev] = n;
|
||||
utf8::next(i, e);
|
||||
++n;
|
||||
unsigned d = std::distance(b, i);
|
||||
while (prev < d)
|
||||
b2u[++prev] = n;
|
||||
}
|
||||
b2u[++prev] = ++n;
|
||||
|
||||
|
|
@ -58,9 +58,9 @@ namespace spot
|
|||
parse_error_list::iterator it;
|
||||
for (it = error_list.begin(); it != error_list.end(); ++it)
|
||||
{
|
||||
location& l = it->first;
|
||||
l.begin.column = b2u[l.begin.column];
|
||||
l.end.column = b2u[l.end.column];
|
||||
location& l = it->first;
|
||||
l.begin.column = b2u[l.begin.column];
|
||||
l.end.column = b2u[l.end.column];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,45 +68,45 @@ namespace spot
|
|||
{
|
||||
static bool
|
||||
format_parse_errors_aux(std::ostream& os,
|
||||
const std::string& ltl_string,
|
||||
const parse_error_list& error_list,
|
||||
unsigned shift)
|
||||
const std::string& ltl_string,
|
||||
const parse_error_list& error_list,
|
||||
unsigned shift)
|
||||
{
|
||||
bool printed = false;
|
||||
for (auto it: error_list)
|
||||
{
|
||||
os << ">>> " << ltl_string << '\n';
|
||||
const location& l = it.first;
|
||||
{
|
||||
os << ">>> " << ltl_string << '\n';
|
||||
const location& l = it.first;
|
||||
|
||||
unsigned n = 1;
|
||||
for (; n < 4 + l.begin.column + shift; ++n)
|
||||
os << ' ';
|
||||
// Write at least one '^', even if begin==end.
|
||||
os << '^';
|
||||
++n;
|
||||
for (; n < 4 + l.end.column + shift; ++n)
|
||||
os << '^';
|
||||
os << '\n' << it.second << "\n\n";
|
||||
printed = true;
|
||||
}
|
||||
unsigned n = 1;
|
||||
for (; n < 4 + l.begin.column + shift; ++n)
|
||||
os << ' ';
|
||||
// Write at least one '^', even if begin==end.
|
||||
os << '^';
|
||||
++n;
|
||||
for (; n < 4 + l.end.column + shift; ++n)
|
||||
os << '^';
|
||||
os << '\n' << it.second << "\n\n";
|
||||
printed = true;
|
||||
}
|
||||
return printed;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
parsed_formula::format_errors(std::ostream& os,
|
||||
const std::string& real_input,
|
||||
unsigned shift)
|
||||
const std::string& real_input,
|
||||
unsigned shift)
|
||||
{
|
||||
if (utf8::is_valid(input.begin(), input.end()))
|
||||
{
|
||||
parse_error_list fixed = errors;
|
||||
fix_utf8_locations(input, fixed);
|
||||
return format_parse_errors_aux(os, real_input, fixed, shift);
|
||||
parse_error_list fixed = errors;
|
||||
fix_utf8_locations(input, fixed);
|
||||
return format_parse_errors_aux(os, real_input, fixed, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
return format_parse_errors_aux(os, real_input, errors, shift);
|
||||
return format_parse_errors_aux(os, real_input, errors, shift);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@
|
|||
|
||||
# define YY_DECL \
|
||||
int tlyylex (tlyy::parser::semantic_type *yylval, \
|
||||
spot::location *yylloc, \
|
||||
spot::parse_error_list& error_list)
|
||||
spot::location *yylloc, \
|
||||
spot::parse_error_list& error_list)
|
||||
YY_DECL;
|
||||
|
||||
void flex_set_buffer(const std::string& buf, int start_tok, bool lenient);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace spot
|
|||
{
|
||||
auto i = map_.find(name);
|
||||
if (i != map_.end())
|
||||
return true;
|
||||
return true;
|
||||
auto v = aut_->acc().add_set();
|
||||
map_[name] = v;
|
||||
return true;
|
||||
|
|
@ -63,7 +63,7 @@ namespace spot
|
|||
{
|
||||
auto p = map_.find(name);
|
||||
if (p == map_.end())
|
||||
return std::make_pair(false, 0U);
|
||||
return std::make_pair(false, 0U);
|
||||
return std::make_pair(true, acc_cond::mark_t({p->second}));
|
||||
}
|
||||
};
|
||||
|
|
@ -83,9 +83,9 @@ namespace spot
|
|||
std::pair<bool, acc_cond::mark_t> lookup(unsigned n)
|
||||
{
|
||||
if (n < aut_->acc().num_sets())
|
||||
return std::make_pair(true, acc_cond::mark_t({n}));
|
||||
return std::make_pair(true, acc_cond::mark_t({n}));
|
||||
else
|
||||
return std::make_pair(false, 0U);
|
||||
return std::make_pair(false, 0U);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -106,13 +106,13 @@ namespace spot
|
|||
{
|
||||
auto p = map_.find(n);
|
||||
if (p != map_.end())
|
||||
return std::make_pair(true, p->second);
|
||||
return std::make_pair(true, p->second);
|
||||
if (used_ < aut_->acc().num_sets())
|
||||
{
|
||||
auto res = acc_cond::mark_t({used_++});
|
||||
map_[n] = res;
|
||||
return std::make_pair(true, res);
|
||||
}
|
||||
{
|
||||
auto res = acc_cond::mark_t({used_++});
|
||||
map_[n] = res;
|
||||
return std::make_pair(true, res);
|
||||
}
|
||||
return std::make_pair(false, 0U);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -67,15 +67,15 @@ namespace spot
|
|||
// externally), use the new variables.
|
||||
if (lvarnum < varnum)
|
||||
{
|
||||
more -= varnum - lvarnum;
|
||||
lvarnum = varnum;
|
||||
more -= varnum - lvarnum;
|
||||
lvarnum = varnum;
|
||||
}
|
||||
// If we still need more variable, do allocate them.
|
||||
if (more > 0)
|
||||
{
|
||||
bdd_extvarnum(more);
|
||||
varnum += more;
|
||||
lvarnum = varnum;
|
||||
bdd_extvarnum(more);
|
||||
varnum += more;
|
||||
lvarnum = varnum;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,19 +98,19 @@ namespace spot
|
|||
// of the variable space, allocate just the difference.
|
||||
if (!fl.empty() && fl.back().first + fl.back().second == lvarnum)
|
||||
{
|
||||
int res = fl.back().first;
|
||||
int endvar = fl.back().second;
|
||||
assert(n > endvar);
|
||||
extvarnum(n - endvar);
|
||||
fl.pop_back();
|
||||
return res;
|
||||
int res = fl.back().first;
|
||||
int endvar = fl.back().second;
|
||||
assert(n > endvar);
|
||||
extvarnum(n - endvar);
|
||||
fl.pop_back();
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, allocate as much variables as we need.
|
||||
int res = lvarnum;
|
||||
extvarnum(n);
|
||||
return res;
|
||||
// Otherwise, allocate as much variables as we need.
|
||||
int res = lvarnum;
|
||||
extvarnum(n);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,24 +41,24 @@ namespace spot
|
|||
free_list_type::iterator cur;
|
||||
for (cur = fl.begin(); cur != fl.end(); ++cur)
|
||||
{
|
||||
if (cur->second < n)
|
||||
continue;
|
||||
if (n == cur->second)
|
||||
{
|
||||
best = cur;
|
||||
break;
|
||||
}
|
||||
if (best == fl.end()
|
||||
|| cur->second < best->second)
|
||||
best = cur;
|
||||
if (cur->second < n)
|
||||
continue;
|
||||
if (n == cur->second)
|
||||
{
|
||||
best = cur;
|
||||
break;
|
||||
}
|
||||
if (best == fl.end()
|
||||
|| cur->second < best->second)
|
||||
best = cur;
|
||||
}
|
||||
|
||||
// We have found enough free variables.
|
||||
if (best != fl.end())
|
||||
{
|
||||
int result = best->first;
|
||||
remove(best, result, n);
|
||||
return result;
|
||||
int result = best->first;
|
||||
remove(best, result, n);
|
||||
return result;
|
||||
}
|
||||
|
||||
// We haven't found enough adjacent free variables;
|
||||
|
|
@ -73,67 +73,67 @@ namespace spot
|
|||
int end = base + n;
|
||||
for (cur = fl.begin(); cur != fl.end(); ++cur)
|
||||
{
|
||||
int cend = cur->first + cur->second;
|
||||
// cur [...]
|
||||
// to insert [...]
|
||||
// -----------------------
|
||||
// result [...] [...]
|
||||
// (Insert a new range, unconnected.)
|
||||
if (cur->first > end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// cur [...]
|
||||
// to insert [...]
|
||||
// -----------------------
|
||||
// result unknown : we should look at the rest of the freelist.
|
||||
else if (base > cend)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// cur [....[ [......[
|
||||
// to insert [....[ [..[
|
||||
// ----------------------------------
|
||||
// result [......[ [......[
|
||||
else if (cur->first <= base)
|
||||
{
|
||||
if (cend >= end)
|
||||
// second case : nothing to do
|
||||
return;
|
||||
// cur->second is set below.
|
||||
}
|
||||
// cur [....[ [..[
|
||||
// to insert [....[ [.......[
|
||||
// ----------------------------------
|
||||
// result [......[ [.......[
|
||||
else
|
||||
{
|
||||
cur->first = base;
|
||||
// cur->second is set below.
|
||||
}
|
||||
int cend = cur->first + cur->second;
|
||||
// cur [...]
|
||||
// to insert [...]
|
||||
// -----------------------
|
||||
// result [...] [...]
|
||||
// (Insert a new range, unconnected.)
|
||||
if (cur->first > end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// cur [...]
|
||||
// to insert [...]
|
||||
// -----------------------
|
||||
// result unknown : we should look at the rest of the freelist.
|
||||
else if (base > cend)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// cur [....[ [......[
|
||||
// to insert [....[ [..[
|
||||
// ----------------------------------
|
||||
// result [......[ [......[
|
||||
else if (cur->first <= base)
|
||||
{
|
||||
if (cend >= end)
|
||||
// second case : nothing to do
|
||||
return;
|
||||
// cur->second is set below.
|
||||
}
|
||||
// cur [....[ [..[
|
||||
// to insert [....[ [.......[
|
||||
// ----------------------------------
|
||||
// result [......[ [.......[
|
||||
else
|
||||
{
|
||||
cur->first = base;
|
||||
// cur->second is set below.
|
||||
}
|
||||
|
||||
// We get here in one of these three situations:
|
||||
//
|
||||
// cur [....[ [....[ [..[
|
||||
// to insert [....[ [....[ [.......[
|
||||
// -------------------------------------------
|
||||
// result [......[ [......[ [.......[
|
||||
//
|
||||
// cur->first is already set, be cur->second has yet to be.
|
||||
end = std::max(cend, end);
|
||||
cur->second = end - cur->first;
|
||||
// Since we have extended the current range, maybe the next
|
||||
// items on the list should be merged.
|
||||
free_list_type::iterator next = cur;
|
||||
++next;
|
||||
while (next != fl.end() && next->first <= end)
|
||||
{
|
||||
end = std::max(next->first + next->second, end);
|
||||
cur->second = end - cur->first;
|
||||
free_list_type::iterator next2 = next++;
|
||||
fl.erase(next2);
|
||||
}
|
||||
return;
|
||||
// We get here in one of these three situations:
|
||||
//
|
||||
// cur [....[ [....[ [..[
|
||||
// to insert [....[ [....[ [.......[
|
||||
// -------------------------------------------
|
||||
// result [......[ [......[ [.......[
|
||||
//
|
||||
// cur->first is already set, be cur->second has yet to be.
|
||||
end = std::max(cend, end);
|
||||
cur->second = end - cur->first;
|
||||
// Since we have extended the current range, maybe the next
|
||||
// items on the list should be merged.
|
||||
free_list_type::iterator next = cur;
|
||||
++next;
|
||||
while (next != fl.end() && next->first <= end)
|
||||
{
|
||||
end = std::max(next->first + next->second, end);
|
||||
cur->second = end - cur->first;
|
||||
free_list_type::iterator next2 = next++;
|
||||
fl.erase(next2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We reach this place either because a new unconnected range
|
||||
|
|
@ -148,15 +148,15 @@ namespace spot
|
|||
int end = base + n;
|
||||
while (cur != fl.end() && cur->first < end)
|
||||
{
|
||||
int cend = cur->first + cur->second;
|
||||
// Remove may invalidate the current iterator, so advance it first.
|
||||
free_list_type::iterator old = cur++;
|
||||
if (cend >= base)
|
||||
{
|
||||
int newbase = std::max(base, old->first);
|
||||
int q = std::min(cend, end) - newbase;
|
||||
remove(old, newbase, q);
|
||||
}
|
||||
int cend = cur->first + cur->second;
|
||||
// Remove may invalidate the current iterator, so advance it first.
|
||||
free_list_type::iterator old = cur++;
|
||||
if (cend >= base)
|
||||
{
|
||||
int newbase = std::max(base, old->first);
|
||||
int q = std::min(cend, end) - newbase;
|
||||
remove(old, newbase, q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -165,31 +165,31 @@ namespace spot
|
|||
{
|
||||
if (base == i->first)
|
||||
{
|
||||
// Removing at the beginning of the range
|
||||
i->second -= n;
|
||||
assert(i->second >= 0);
|
||||
// Erase the range if it's now empty.
|
||||
if (i->second == 0)
|
||||
fl.erase(i);
|
||||
else
|
||||
i->first += n;
|
||||
// Removing at the beginning of the range
|
||||
i->second -= n;
|
||||
assert(i->second >= 0);
|
||||
// Erase the range if it's now empty.
|
||||
if (i->second == 0)
|
||||
fl.erase(i);
|
||||
else
|
||||
i->first += n;
|
||||
}
|
||||
else if (base + n == i->first + i->second)
|
||||
{
|
||||
// Removing at the end of the range
|
||||
i->second -= n;
|
||||
assert(i->second > 0); // cannot be empty because base != i->first
|
||||
// Removing at the end of the range
|
||||
i->second -= n;
|
||||
assert(i->second > 0); // cannot be empty because base != i->first
|
||||
}
|
||||
else
|
||||
{
|
||||
// Removing in the middle of a range.
|
||||
int b1 = i->first;
|
||||
int n1 = base - i->first;
|
||||
int n2 = i->first + i->second - base - n;
|
||||
assert(n1 > 0);
|
||||
assert(n2 > 0);
|
||||
*i = pos_lenght_pair(base + n, n2);
|
||||
fl.insert(i, pos_lenght_pair(b1, n1));
|
||||
// Removing in the middle of a range.
|
||||
int b1 = i->first;
|
||||
int n1 = base - i->first;
|
||||
int n2 = i->first + i->second - base - n;
|
||||
assert(n1 > 0);
|
||||
assert(n2 > 0);
|
||||
*i = pos_lenght_pair(base + n, n2);
|
||||
fl.insert(i, pos_lenght_pair(b1, n1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ namespace spot
|
|||
trim(std::string& str)
|
||||
{
|
||||
str.erase(std::find_if(str.rbegin(), str.rend(),
|
||||
std::not1(std::ptr_fun<int, int>
|
||||
(std::isspace))).base(),
|
||||
str.end());
|
||||
std::not1(std::ptr_fun<int, int>
|
||||
(std::isspace))).base(),
|
||||
str.end());
|
||||
str.erase(str.begin(),
|
||||
std::find_if(str.begin(), str.end(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||
std::find_if(str.begin(), str.end(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace spot
|
|||
{
|
||||
for (auto s: a.sets())
|
||||
if (m[s] > 0)
|
||||
--m[s];
|
||||
--m[s];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ namespace spot
|
|||
std::vector<unsigned> res;
|
||||
for (unsigned n = 0; n < max; ++n)
|
||||
if (m[n] > w.m[n])
|
||||
res.push_back(n);
|
||||
res.push_back(n);
|
||||
return acc_cond::mark_t(res.begin(), res.end());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace spot
|
|||
/// the corresponding counter in w.
|
||||
acc_cond::mark_t diff(const acc_cond& acc, const weight& w) const;
|
||||
friend std::ostream& operator<<(std::ostream& os,
|
||||
const weight& w);
|
||||
const weight& w);
|
||||
|
||||
private:
|
||||
std::vector<int> m;
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ namespace spot
|
|||
bool is_stuttering_transition = (get_tgba_condition()
|
||||
== (dest)->get_tgba_condition());
|
||||
bool dest_is_livelock_accepting =
|
||||
dest->is_livelock_accepting_state();
|
||||
dest->is_livelock_accepting_state();
|
||||
|
||||
//Before deleting stuttering transitions, propaged back livelock
|
||||
//and initial state's properties
|
||||
|
|
@ -319,7 +319,7 @@ namespace spot
|
|||
// they are not cloned.
|
||||
if (trans)
|
||||
for (auto& t: *trans)
|
||||
delete t;
|
||||
delete t;
|
||||
delete trans;
|
||||
|
||||
std::unordered_map<int, transitions*, std::hash<int> >::iterator i =
|
||||
|
|
@ -338,8 +338,8 @@ namespace spot
|
|||
|
||||
|
||||
ta_explicit::ta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state):
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state):
|
||||
ta(tgba->get_dict()),
|
||||
tgba_(tgba),
|
||||
artificial_initial_state_(artificial_initial_state)
|
||||
|
|
@ -351,7 +351,7 @@ namespace spot
|
|||
{
|
||||
auto is = add_state(artificial_initial_state);
|
||||
assert(is == artificial_initial_state);
|
||||
(void)is;
|
||||
(void)is;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -361,8 +361,8 @@ namespace spot
|
|||
for (it = states_set_.begin(); it != states_set_.end(); ++it)
|
||||
{
|
||||
auto* s = const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(*it));
|
||||
assert(s);
|
||||
(down_cast<const state_ta_explicit*>(*it));
|
||||
assert(s);
|
||||
s->free_transitions();
|
||||
s->get_tgba_state()->destroy();
|
||||
delete s;
|
||||
|
|
@ -390,11 +390,11 @@ namespace spot
|
|||
auto add_state = initial_states_set_.insert(s);
|
||||
if (get_artificial_initial_state())
|
||||
if (add_state.second)
|
||||
{
|
||||
auto i =
|
||||
down_cast<state_ta_explicit*>(get_artificial_initial_state());
|
||||
create_transition(i, condition, 0U, s);
|
||||
}
|
||||
{
|
||||
auto i =
|
||||
down_cast<state_ta_explicit*>(get_artificial_initial_state());
|
||||
create_transition(i, condition, 0U, s);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -411,9 +411,9 @@ namespace spot
|
|||
|
||||
void
|
||||
ta_explicit::create_transition(state_ta_explicit* source, bdd condition,
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
const state_ta_explicit* dest,
|
||||
bool add_at_beginning)
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
const state_ta_explicit* dest,
|
||||
bool add_at_beginning)
|
||||
{
|
||||
state_ta_explicit::transition* t = new state_ta_explicit::transition;
|
||||
t->dest = dest;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
ta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr);
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr);
|
||||
|
||||
const_twa_ptr
|
||||
get_tgba() const;
|
||||
|
|
@ -55,9 +55,9 @@ namespace spot
|
|||
|
||||
void
|
||||
create_transition(state_ta_explicit* source, bdd condition,
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
const state_ta_explicit* dest,
|
||||
bool add_at_beginning = false);
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
const state_ta_explicit* dest,
|
||||
bool add_at_beginning = false);
|
||||
|
||||
void
|
||||
delete_stuttering_transitions();
|
||||
|
|
@ -142,10 +142,10 @@ namespace spot
|
|||
typedef std::list<transition*> transitions;
|
||||
|
||||
state_ta_explicit(const state* tgba_state, const bdd tgba_condition,
|
||||
bool is_initial_state = false,
|
||||
bool is_accepting_state = false,
|
||||
bool is_livelock_accepting_state = false,
|
||||
transitions* trans = nullptr) :
|
||||
bool is_initial_state = false,
|
||||
bool is_accepting_state = false,
|
||||
bool is_livelock_accepting_state = false,
|
||||
transitions* trans = nullptr) :
|
||||
tgba_state_(tgba_state), tgba_condition_(tgba_condition),
|
||||
is_initial_state_(is_initial_state), is_accepting_state_(
|
||||
is_accepting_state), is_livelock_accepting_state_(
|
||||
|
|
@ -246,8 +246,8 @@ namespace spot
|
|||
|
||||
inline ta_explicit_ptr
|
||||
make_ta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr)
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr)
|
||||
{
|
||||
return std::make_shared<ta_explicit>(tgba, n_acc, artificial_initial_state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ namespace spot
|
|||
////////////////////////////////////////////////////////////
|
||||
// ta_succ_iterator_product
|
||||
ta_succ_iterator_product::ta_succ_iterator_product(const state_ta_product* s,
|
||||
const ta* t,
|
||||
const kripke* k)
|
||||
const ta* t,
|
||||
const kripke* k)
|
||||
: source_(s), ta_(t), kripke_(k)
|
||||
{
|
||||
kripke_source_condition = kripke_->state_condition(s->get_kripke_state());
|
||||
|
|
@ -243,7 +243,7 @@ namespace spot
|
|||
|
||||
|
||||
ta_product::ta_product(const const_ta_ptr& testing_automata,
|
||||
const const_kripke_ptr& kripke_structure):
|
||||
const const_kripke_ptr& kripke_structure):
|
||||
ta(testing_automata->get_dict()),
|
||||
dict_(testing_automata->get_dict()),
|
||||
ta_(testing_automata),
|
||||
|
|
@ -292,9 +292,9 @@ namespace spot
|
|||
|
||||
for (auto s: ta_init_states_set)
|
||||
if (artificial_initial_state ||
|
||||
(kripke_init_condition == ta_->get_state_condition(s)))
|
||||
initial_states_set.insert(new state_ta_product(s,
|
||||
kripke_init->clone()));
|
||||
(kripke_init_condition == ta_->get_state_condition(s)))
|
||||
initial_states_set.insert(new state_ta_product(s,
|
||||
kripke_init->clone()));
|
||||
|
||||
kripke_init->destroy();
|
||||
return initial_states_set;
|
||||
|
|
@ -316,8 +316,8 @@ namespace spot
|
|||
const state_ta_product* stp = down_cast<const state_ta_product*> (s);
|
||||
assert(s);
|
||||
return new ta_succ_iterator_product_by_changeset(stp,
|
||||
ta_.get(), kripke_.get(),
|
||||
changeset);
|
||||
ta_.get(), kripke_.get(),
|
||||
changeset);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -402,7 +402,7 @@ namespace spot
|
|||
|
||||
ta_succ_iterator_product_by_changeset::
|
||||
ta_succ_iterator_product_by_changeset(const state_ta_product* s, const ta* t,
|
||||
const kripke* k, bdd changeset)
|
||||
const kripke* k, bdd changeset)
|
||||
: ta_succ_iterator_product(s, t, k)
|
||||
{
|
||||
current_condition_ = changeset;
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ namespace spot
|
|||
/// \param testing_automaton The TA component in the product.
|
||||
/// \param kripke_structure The Kripke component in the product.
|
||||
ta_product(const const_ta_ptr& testing_automaton,
|
||||
const const_kripke_ptr& kripke_structure);
|
||||
const const_kripke_ptr& kripke_structure);
|
||||
|
||||
virtual
|
||||
~ta_product();
|
||||
|
|
@ -197,7 +197,7 @@ namespace spot
|
|||
typedef std::shared_ptr<ta_product> ta_product_ptr;
|
||||
typedef std::shared_ptr<const ta_product> const_ta_product_ptr;
|
||||
inline ta_product_ptr product(const const_ta_ptr& testing_automaton,
|
||||
const const_kripke_ptr& kripke_structure)
|
||||
const const_kripke_ptr& kripke_structure)
|
||||
{
|
||||
return std::make_shared<ta_product>(testing_automaton, kripke_structure);
|
||||
}
|
||||
|
|
@ -207,8 +207,8 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
ta_succ_iterator_product_by_changeset(const state_ta_product* s,
|
||||
const ta* t, const kripke* k,
|
||||
bdd changeset);
|
||||
const ta* t, const kripke* k,
|
||||
bdd changeset);
|
||||
|
||||
/// \brief Move to the next successor in the Kripke structure
|
||||
void next_kripke_dest();
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ namespace spot
|
|||
{
|
||||
|
||||
tgta_explicit::tgta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state) :
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state) :
|
||||
tgta(tgba->get_dict()),
|
||||
ta_(make_ta_explicit(tgba, n_acc, artificial_initial_state))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
tgta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state);
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state);
|
||||
|
||||
// tgba interface
|
||||
virtual spot::state* get_init_state() const override;
|
||||
|
|
@ -63,9 +63,9 @@ namespace spot
|
|||
|
||||
inline tgta_explicit_ptr
|
||||
make_tgta_explicit(const const_twa_ptr& tgba, unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr)
|
||||
state_ta_explicit* artificial_initial_state = nullptr)
|
||||
{
|
||||
return std::make_shared<tgta_explicit>(tgba, n_acc,
|
||||
artificial_initial_state);
|
||||
artificial_initial_state);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace spot
|
|||
// tgta_product
|
||||
|
||||
tgta_product::tgta_product(const const_kripke_ptr& left,
|
||||
const const_tgta_ptr& right):
|
||||
const const_tgta_ptr& right):
|
||||
twa_product(left, right)
|
||||
{
|
||||
}
|
||||
|
|
@ -207,7 +207,7 @@ namespace spot
|
|||
kripke_current_dest_state->clone(),
|
||||
tgta_succ_it_->dst(), pool_);
|
||||
current_acceptance_conditions_
|
||||
= tgta_succ_it_->acc();
|
||||
= tgta_succ_it_->acc();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
tgta_product(const const_kripke_ptr& left,
|
||||
const const_tgta_ptr& right);
|
||||
const const_tgta_ptr& right);
|
||||
|
||||
virtual const state* get_init_state() const override;
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ namespace spot
|
|||
};
|
||||
|
||||
inline twa_ptr product(const const_kripke_ptr& left,
|
||||
const const_tgta_ptr& right)
|
||||
const const_tgta_ptr& right)
|
||||
{
|
||||
return std::make_shared<tgta_product>(left, right);
|
||||
}
|
||||
|
|
@ -52,9 +52,9 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
tgta_succ_iterator_product(const state_product* s,
|
||||
const const_kripke_ptr& k,
|
||||
const const_tgta_ptr& tgta,
|
||||
fixed_size_pool* pool);
|
||||
const const_kripke_ptr& k,
|
||||
const const_tgta_ptr& tgta,
|
||||
fixed_size_pool* pool);
|
||||
|
||||
virtual
|
||||
~tgta_succ_iterator_product();
|
||||
|
|
|
|||
|
|
@ -35,109 +35,109 @@ namespace spot
|
|||
void
|
||||
parse_opts(const char* options)
|
||||
{
|
||||
const char* orig = options;
|
||||
while (char c = *options++)
|
||||
switch (c)
|
||||
{
|
||||
case '.':
|
||||
{
|
||||
// Copy the value in a string, so future calls to
|
||||
// parse_opts do not fail if the environment has
|
||||
// changed. (This matters particularly in an ipython
|
||||
// notebook, where it is tempting to redefine
|
||||
// SPOT_DOTDEFAULT.)
|
||||
static std::string def = []()
|
||||
{
|
||||
auto s = getenv("SPOT_DOTDEFAULT");
|
||||
return s ? s : "";
|
||||
}();
|
||||
// Prevent infinite recursions...
|
||||
if (orig == def.c_str())
|
||||
throw std::runtime_error
|
||||
(std::string("SPOT_DOTDEFAULT should not contain '.'"));
|
||||
if (!def.empty())
|
||||
parse_opts(def.c_str());
|
||||
break;
|
||||
}
|
||||
case 'A':
|
||||
opt_hide_sets_ = true;
|
||||
break;
|
||||
case 'c':
|
||||
opt_circles_ = true;
|
||||
break;
|
||||
case 'C':
|
||||
if (*options != '(')
|
||||
throw std::runtime_error
|
||||
("invalid node color specification for print_dot()");
|
||||
{
|
||||
auto* end = strchr(++options, ')');
|
||||
if (!end)
|
||||
throw std::runtime_error
|
||||
("invalid node color specification for print_dot()");
|
||||
opt_node_color_ = std::string(options, end - options);
|
||||
options = end + 1;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
opt_horizontal_ = true;
|
||||
break;
|
||||
case 'f':
|
||||
if (*options != '(')
|
||||
throw std::runtime_error
|
||||
(std::string("invalid font specification for dotty()"));
|
||||
{
|
||||
auto* end = strchr(++options, ')');
|
||||
if (!end)
|
||||
throw std::runtime_error
|
||||
(std::string("invalid font specification for dotty()"));
|
||||
opt_font_ = std::string(options, end - options);
|
||||
options = end + 1;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
opt_horizontal_ = false;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'B':
|
||||
case 'e':
|
||||
case 'n':
|
||||
case 'N':
|
||||
case 'o':
|
||||
case 'r':
|
||||
case 'R':
|
||||
case 's':
|
||||
case 't':
|
||||
case '+':
|
||||
case '<':
|
||||
case '#':
|
||||
// All these options are implemented by dotty() on TGBA,
|
||||
// but are not implemented here. We simply ignore them,
|
||||
// because raising an exception if they are in
|
||||
// SPOT_DEFAULT would be annoying.
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error
|
||||
(std::string("unknown option for dotty(): ") + c);
|
||||
}
|
||||
const char* orig = options;
|
||||
while (char c = *options++)
|
||||
switch (c)
|
||||
{
|
||||
case '.':
|
||||
{
|
||||
// Copy the value in a string, so future calls to
|
||||
// parse_opts do not fail if the environment has
|
||||
// changed. (This matters particularly in an ipython
|
||||
// notebook, where it is tempting to redefine
|
||||
// SPOT_DOTDEFAULT.)
|
||||
static std::string def = []()
|
||||
{
|
||||
auto s = getenv("SPOT_DOTDEFAULT");
|
||||
return s ? s : "";
|
||||
}();
|
||||
// Prevent infinite recursions...
|
||||
if (orig == def.c_str())
|
||||
throw std::runtime_error
|
||||
(std::string("SPOT_DOTDEFAULT should not contain '.'"));
|
||||
if (!def.empty())
|
||||
parse_opts(def.c_str());
|
||||
break;
|
||||
}
|
||||
case 'A':
|
||||
opt_hide_sets_ = true;
|
||||
break;
|
||||
case 'c':
|
||||
opt_circles_ = true;
|
||||
break;
|
||||
case 'C':
|
||||
if (*options != '(')
|
||||
throw std::runtime_error
|
||||
("invalid node color specification for print_dot()");
|
||||
{
|
||||
auto* end = strchr(++options, ')');
|
||||
if (!end)
|
||||
throw std::runtime_error
|
||||
("invalid node color specification for print_dot()");
|
||||
opt_node_color_ = std::string(options, end - options);
|
||||
options = end + 1;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
opt_horizontal_ = true;
|
||||
break;
|
||||
case 'f':
|
||||
if (*options != '(')
|
||||
throw std::runtime_error
|
||||
(std::string("invalid font specification for dotty()"));
|
||||
{
|
||||
auto* end = strchr(++options, ')');
|
||||
if (!end)
|
||||
throw std::runtime_error
|
||||
(std::string("invalid font specification for dotty()"));
|
||||
opt_font_ = std::string(options, end - options);
|
||||
options = end + 1;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
opt_horizontal_ = false;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'B':
|
||||
case 'e':
|
||||
case 'n':
|
||||
case 'N':
|
||||
case 'o':
|
||||
case 'r':
|
||||
case 'R':
|
||||
case 's':
|
||||
case 't':
|
||||
case '+':
|
||||
case '<':
|
||||
case '#':
|
||||
// All these options are implemented by dotty() on TGBA,
|
||||
// but are not implemented here. We simply ignore them,
|
||||
// because raising an exception if they are in
|
||||
// SPOT_DEFAULT would be annoying.
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error
|
||||
(std::string("unknown option for dotty(): ") + c);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
dotty_bfs(std::ostream& os, const const_ta_ptr& a,
|
||||
const char* opt) :
|
||||
const char* opt) :
|
||||
ta_reachable_iterator_breadth_first(a), os_(os)
|
||||
{
|
||||
parse_opts(opt ? opt : ".");
|
||||
parse_opts(opt ? opt : ".");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -145,56 +145,56 @@ namespace spot
|
|||
{
|
||||
os_ << "digraph G {\n";
|
||||
|
||||
if (opt_horizontal_)
|
||||
os_ << " rankdir=LR\n";
|
||||
if (opt_circles_)
|
||||
os_ << " node [shape=\"circle\"]\n";
|
||||
if (!opt_node_color_.empty())
|
||||
os_ << " node [style=\"filled\", fillcolor=\""
|
||||
<< opt_node_color_ << "\"]\n";
|
||||
if (!opt_font_.empty())
|
||||
os_ << " fontname=\"" << opt_font_
|
||||
<< "\"\n node [fontname=\"" << opt_font_
|
||||
<< "\"]\n edge [fontname=\"" << opt_font_
|
||||
<< "\"]\n";
|
||||
if (opt_horizontal_)
|
||||
os_ << " rankdir=LR\n";
|
||||
if (opt_circles_)
|
||||
os_ << " node [shape=\"circle\"]\n";
|
||||
if (!opt_node_color_.empty())
|
||||
os_ << " node [style=\"filled\", fillcolor=\""
|
||||
<< opt_node_color_ << "\"]\n";
|
||||
if (!opt_font_.empty())
|
||||
os_ << " fontname=\"" << opt_font_
|
||||
<< "\"\n node [fontname=\"" << opt_font_
|
||||
<< "\"]\n edge [fontname=\"" << opt_font_
|
||||
<< "\"]\n";
|
||||
|
||||
// Always copy the environment variable into a static string,
|
||||
// so that we (1) look it up once, but (2) won't crash if the
|
||||
// environment is changed.
|
||||
static std::string extra = []()
|
||||
{
|
||||
auto s = getenv("SPOT_DOTEXTRA");
|
||||
return s ? s : "";
|
||||
}();
|
||||
// Any extra text passed in the SPOT_DOTEXTRA environment
|
||||
// variable should be output at the end of the "header", so
|
||||
// that our setup can be overridden.
|
||||
if (!extra.empty())
|
||||
os_ << " " << extra << '\n';
|
||||
// Always copy the environment variable into a static string,
|
||||
// so that we (1) look it up once, but (2) won't crash if the
|
||||
// environment is changed.
|
||||
static std::string extra = []()
|
||||
{
|
||||
auto s = getenv("SPOT_DOTEXTRA");
|
||||
return s ? s : "";
|
||||
}();
|
||||
// Any extra text passed in the SPOT_DOTEXTRA environment
|
||||
// variable should be output at the end of the "header", so
|
||||
// that our setup can be overridden.
|
||||
if (!extra.empty())
|
||||
os_ << " " << extra << '\n';
|
||||
|
||||
artificial_initial_state_ = t_automata_->get_artificial_initial_state();
|
||||
|
||||
ta::const_states_set_t init_states_set;
|
||||
|
||||
if (artificial_initial_state_)
|
||||
{
|
||||
init_states_set.insert(artificial_initial_state_);
|
||||
os_ << " 0 [label=\"\", style=invis, height=0]\n 0 -> 1\n";
|
||||
}
|
||||
{
|
||||
init_states_set.insert(artificial_initial_state_);
|
||||
os_ << " 0 [label=\"\", style=invis, height=0]\n 0 -> 1\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = 0;
|
||||
init_states_set = t_automata_->get_initial_states_set();
|
||||
for (auto s: init_states_set)
|
||||
{
|
||||
bdd init_condition = t_automata_->get_state_condition(s);
|
||||
std::string label = bdd_format_formula(t_automata_->get_dict(),
|
||||
init_condition);
|
||||
++n;
|
||||
os_ << " " << -n << " [label=\"\", style=invis, height=0]\n "
|
||||
<< -n << " -> " << n << " [label=\"" << label << "\"]\n";
|
||||
}
|
||||
}
|
||||
{
|
||||
int n = 0;
|
||||
init_states_set = t_automata_->get_initial_states_set();
|
||||
for (auto s: init_states_set)
|
||||
{
|
||||
bdd init_condition = t_automata_->get_state_condition(s);
|
||||
std::string label = bdd_format_formula(t_automata_->get_dict(),
|
||||
init_condition);
|
||||
++n;
|
||||
os_ << " " << -n << " [label=\"\", style=invis, height=0]\n "
|
||||
<< -n << " -> " << n << " [label=\"" << label << "\"]\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -209,41 +209,41 @@ namespace spot
|
|||
|
||||
std::string style;
|
||||
if (t_automata_->is_accepting_state(s))
|
||||
style = ",peripheries=2";
|
||||
style = ",peripheries=2";
|
||||
|
||||
if (t_automata_->is_livelock_accepting_state(s))
|
||||
style += ",shape=box";
|
||||
if (t_automata_->is_livelock_accepting_state(s))
|
||||
style += ",shape=box";
|
||||
|
||||
os_ << " " << n << " [label=";
|
||||
if (s == artificial_initial_state_)
|
||||
os_ << "init";
|
||||
else
|
||||
os_ << quote_unless_bare_word(t_automata_->format_state(s));
|
||||
os_ << style << "]\n";
|
||||
os_ << " " << n << " [label=";
|
||||
if (s == artificial_initial_state_)
|
||||
os_ << "init";
|
||||
else
|
||||
os_ << quote_unless_bare_word(t_automata_->format_state(s));
|
||||
os_ << style << "]\n";
|
||||
}
|
||||
|
||||
void
|
||||
process_link(int in, int out, const ta_succ_iterator* si)
|
||||
{
|
||||
bdd_dict_ptr d = t_automata_->get_dict();
|
||||
std::string label =
|
||||
((in == 1 && artificial_initial_state_)
|
||||
? bdd_format_formula(d, si->cond())
|
||||
: bdd_format_accset(d, si->cond()));
|
||||
bdd_dict_ptr d = t_automata_->get_dict();
|
||||
std::string label =
|
||||
((in == 1 && artificial_initial_state_)
|
||||
? bdd_format_formula(d, si->cond())
|
||||
: bdd_format_accset(d, si->cond()));
|
||||
|
||||
if (label.empty())
|
||||
label = "{}";
|
||||
if (label.empty())
|
||||
label = "{}";
|
||||
|
||||
if (!opt_hide_sets_)
|
||||
{
|
||||
label += "\n";
|
||||
label += t_automata_->acc().
|
||||
format(si->acc());
|
||||
}
|
||||
if (!opt_hide_sets_)
|
||||
{
|
||||
label += "\n";
|
||||
label += t_automata_->acc().
|
||||
format(si->acc());
|
||||
}
|
||||
|
||||
os_ << " " << in << " -> " << out << " [label=\"";
|
||||
escape_str(os_, label);
|
||||
os_ << "\"]\n";
|
||||
escape_str(os_, label);
|
||||
os_ << "\"]\n";
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -26,5 +26,5 @@ namespace spot
|
|||
{
|
||||
SPOT_API std::ostream&
|
||||
print_dot(std::ostream& os, const const_ta_ptr& a,
|
||||
const char* opt = nullptr);
|
||||
const char* opt = nullptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,10 +102,10 @@ namespace spot
|
|||
(ta_init_it_->dst()), kripke_init_state->clone());
|
||||
|
||||
if (!h.emplace(init, num + 1).second)
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
|
||||
scc.push(++num);
|
||||
arc.push(0U);
|
||||
|
|
@ -146,7 +146,7 @@ namespace spot
|
|||
}
|
||||
|
||||
// fill rem with any component removed,
|
||||
auto i = h.find(curr);
|
||||
auto i = h.find(curr);
|
||||
assert(i != h.end());
|
||||
|
||||
scc.rem().push_front(curr);
|
||||
|
|
@ -168,7 +168,7 @@ namespace spot
|
|||
{
|
||||
// removing states
|
||||
for (auto j: scc.rem())
|
||||
h[j] = -1;
|
||||
h[j] = -1;
|
||||
dec_depth(scc.rem().size());
|
||||
scc.pop();
|
||||
assert(!arc.empty());
|
||||
|
|
@ -209,7 +209,7 @@ namespace spot
|
|||
// We do not need SUCC from now on.
|
||||
|
||||
// Are we going to a new state?
|
||||
auto p = h.emplace(dest, num + 1);
|
||||
auto p = h.emplace(dest, num + 1);
|
||||
if (p.second)
|
||||
{
|
||||
// Number it, stack it, and register its successors
|
||||
|
|
@ -277,23 +277,23 @@ namespace spot
|
|||
|
||||
scc.rem().splice(scc.rem().end(), rem);
|
||||
bool is_accepting_sscc = scc.top().is_accepting
|
||||
|| a_->acc().accepting(scc.top().condition);
|
||||
|| a_->acc().accepting(scc.top().condition);
|
||||
|
||||
if (is_accepting_sscc)
|
||||
{
|
||||
trace
|
||||
<< "PASS 1: SUCCESS: a_->is_livelock_accepting_state(curr): "
|
||||
<< a_->is_livelock_accepting_state(curr) << '\n';
|
||||
<< "PASS 1: SUCCESS: a_->is_livelock_accepting_state(curr): "
|
||||
<< a_->is_livelock_accepting_state(curr) << '\n';
|
||||
trace
|
||||
<< "PASS 1: scc.top().condition : "
|
||||
<< scc.top().condition << '\n';
|
||||
<< scc.top().condition << '\n';
|
||||
trace
|
||||
<< "PASS 1: a_->acc().all_sets() : "
|
||||
<< (a_->acc().all_sets()) << '\n';
|
||||
<< (a_->acc().all_sets()) << '\n';
|
||||
trace
|
||||
<< ("PASS 1 CYCLE and accepting? ")
|
||||
<< a_->acc().accepting(scc.top().condition)
|
||||
<< std::endl;
|
||||
<< ("PASS 1 CYCLE and accepting? ")
|
||||
<< a_->acc().accepting(scc.top().condition)
|
||||
<< std::endl;
|
||||
clear(h, todo, ta_init_it_);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -315,19 +315,19 @@ namespace spot
|
|||
h_livelock_root = h[livelock_roots.top()];
|
||||
|
||||
if (heuristic_livelock_detection(dest, h, h_livelock_root,
|
||||
liveset_curr))
|
||||
liveset_curr))
|
||||
{
|
||||
clear(h, todo, ta_init_it_);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const state* succ: liveset_dest)
|
||||
if (heuristic_livelock_detection(succ, h, h_livelock_root,
|
||||
liveset_curr))
|
||||
{
|
||||
clear(h, todo, ta_init_it_);
|
||||
return true;
|
||||
}
|
||||
if (heuristic_livelock_detection(succ, h, h_livelock_root,
|
||||
liveset_curr))
|
||||
{
|
||||
clear(h, todo, ta_init_it_);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -403,11 +403,11 @@ namespace spot
|
|||
auto init = ta_init_it_.front();
|
||||
ta_init_it_.pop();
|
||||
|
||||
if (!h.emplace(init, num + 1).second)
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
if (!h.emplace(init, num + 1).second)
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
|
||||
sscc.push(num);
|
||||
sscc.top().is_accepting = t->is_livelock_accepting_state(init);
|
||||
|
|
@ -435,7 +435,7 @@ namespace spot
|
|||
trace << "PASS 2 : backtrack\n";
|
||||
|
||||
// fill rem with any component removed,
|
||||
auto i = h.find(curr);
|
||||
auto i = h.find(curr);
|
||||
assert(i != h.end());
|
||||
|
||||
sscc.rem().push_front(curr);
|
||||
|
|
@ -449,7 +449,7 @@ namespace spot
|
|||
{
|
||||
// removing states
|
||||
for (auto j: sscc.rem())
|
||||
h[j] = -1;
|
||||
h[j] = -1;
|
||||
dec_depth(sscc.rem().size());
|
||||
sscc.pop();
|
||||
}
|
||||
|
|
@ -498,10 +498,10 @@ namespace spot
|
|||
inc_depth();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest->destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
dest->destroy();
|
||||
}
|
||||
|
||||
// If we have reached a dead component, ignore it.
|
||||
if (i->second == -1)
|
||||
|
|
@ -509,12 +509,12 @@ namespace spot
|
|||
|
||||
//self loop state
|
||||
if (!curr->compare(i->first))
|
||||
if (t->is_livelock_accepting_state(curr))
|
||||
{
|
||||
clear(h, todo, ta_init_it_);
|
||||
trace << "PASS 2: SUCCESS\n";
|
||||
return true;
|
||||
}
|
||||
if (t->is_livelock_accepting_state(curr))
|
||||
{
|
||||
clear(h, todo, ta_init_it_);
|
||||
trace << "PASS 2: SUCCESS\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now this is the most interesting case. We have reached a
|
||||
// state S1 which is already part of a non-dead SSCC. Any such
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace spot
|
|||
namespace
|
||||
{
|
||||
typedef std::pair<const spot::state*,
|
||||
ta_succ_iterator_product*> pair_state_iter;
|
||||
ta_succ_iterator_product*> pair_state_iter;
|
||||
}
|
||||
|
||||
/// \addtogroup ta_emptiness_check Emptiness-checks
|
||||
|
|
@ -111,7 +111,7 @@ namespace spot
|
|||
/// this heuristic is described in the paper cited above
|
||||
bool
|
||||
check(bool disable_second_pass = false,
|
||||
bool disable_heuristic_for_livelock_detection = false);
|
||||
bool disable_heuristic_for_livelock_detection = false);
|
||||
|
||||
/// \brief Check whether the product automaton contains
|
||||
/// a livelock-accepting run
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ namespace spot
|
|||
{
|
||||
static std::ostream&
|
||||
dump_hash_set(const hash_set* hs,
|
||||
const const_ta_ptr& aut,
|
||||
std::ostream& out)
|
||||
const const_ta_ptr& aut,
|
||||
std::ostream& out)
|
||||
{
|
||||
out << '{';
|
||||
const char* sep = "";
|
||||
|
|
@ -73,7 +73,7 @@ namespace spot
|
|||
// automaton
|
||||
static void
|
||||
build_result(const const_ta_ptr& a, std::list<hash_set*>& sets,
|
||||
twa_graph_ptr result_tgba, const ta_explicit_ptr& result)
|
||||
twa_graph_ptr result_tgba, const ta_explicit_ptr& result)
|
||||
{
|
||||
// For each set, create a state in the tgbaulting automaton.
|
||||
// For a state s, state_num[s] is the number of the state in the minimal
|
||||
|
|
@ -82,103 +82,103 @@ namespace spot
|
|||
std::list<hash_set*>::iterator sit;
|
||||
unsigned num = 0;
|
||||
for (sit = sets.begin(); sit != sets.end(); ++sit)
|
||||
{
|
||||
hash_set::iterator hit;
|
||||
hash_set* h = *sit;
|
||||
for (hit = h->begin(); hit != h->end(); ++hit)
|
||||
state_num[*hit] = num;
|
||||
result_tgba->new_state();
|
||||
++num;
|
||||
}
|
||||
{
|
||||
hash_set::iterator hit;
|
||||
hash_set* h = *sit;
|
||||
for (hit = h->begin(); hit != h->end(); ++hit)
|
||||
state_num[*hit] = num;
|
||||
result_tgba->new_state();
|
||||
++num;
|
||||
}
|
||||
|
||||
// For each transition in the initial automaton, add the corresponding
|
||||
// transition in ta.
|
||||
|
||||
for (sit = sets.begin(); sit != sets.end(); ++sit)
|
||||
{
|
||||
hash_set::iterator hit;
|
||||
hash_set* h = *sit;
|
||||
hit = h->begin();
|
||||
const state* src = *hit;
|
||||
unsigned src_num = state_num[src];
|
||||
{
|
||||
hash_set::iterator hit;
|
||||
hash_set* h = *sit;
|
||||
hit = h->begin();
|
||||
const state* src = *hit;
|
||||
unsigned src_num = state_num[src];
|
||||
|
||||
bdd tgba_condition = bddtrue;
|
||||
bool is_initial_state = a->is_initial_state(src);
|
||||
if (!a->get_artificial_initial_state() && is_initial_state)
|
||||
tgba_condition = a->get_state_condition(src);
|
||||
bool is_accepting_state = a->is_accepting_state(src);
|
||||
bool is_livelock_accepting_state =
|
||||
a->is_livelock_accepting_state(src);
|
||||
bdd tgba_condition = bddtrue;
|
||||
bool is_initial_state = a->is_initial_state(src);
|
||||
if (!a->get_artificial_initial_state() && is_initial_state)
|
||||
tgba_condition = a->get_state_condition(src);
|
||||
bool is_accepting_state = a->is_accepting_state(src);
|
||||
bool is_livelock_accepting_state =
|
||||
a->is_livelock_accepting_state(src);
|
||||
|
||||
state_ta_explicit* new_src =
|
||||
new state_ta_explicit(result_tgba->state_from_number(src_num),
|
||||
tgba_condition, is_initial_state,
|
||||
is_accepting_state,
|
||||
is_livelock_accepting_state);
|
||||
state_ta_explicit* new_src =
|
||||
new state_ta_explicit(result_tgba->state_from_number(src_num),
|
||||
tgba_condition, is_initial_state,
|
||||
is_accepting_state,
|
||||
is_livelock_accepting_state);
|
||||
|
||||
state_ta_explicit* ta_src = result->add_state(new_src);
|
||||
state_ta_explicit* ta_src = result->add_state(new_src);
|
||||
|
||||
if (ta_src != new_src)
|
||||
{
|
||||
delete new_src;
|
||||
}
|
||||
else if (a->get_artificial_initial_state())
|
||||
{
|
||||
if (a->get_artificial_initial_state() == src)
|
||||
result->set_artificial_initial_state(new_src);
|
||||
}
|
||||
else if (is_initial_state)
|
||||
{
|
||||
result->add_to_initial_states_set(new_src);
|
||||
}
|
||||
if (ta_src != new_src)
|
||||
{
|
||||
delete new_src;
|
||||
}
|
||||
else if (a->get_artificial_initial_state())
|
||||
{
|
||||
if (a->get_artificial_initial_state() == src)
|
||||
result->set_artificial_initial_state(new_src);
|
||||
}
|
||||
else if (is_initial_state)
|
||||
{
|
||||
result->add_to_initial_states_set(new_src);
|
||||
}
|
||||
|
||||
ta_succ_iterator* succit = a->succ_iter(src);
|
||||
ta_succ_iterator* succit = a->succ_iter(src);
|
||||
|
||||
for (succit->first(); !succit->done(); succit->next())
|
||||
{
|
||||
const state* dst = succit->dst();
|
||||
hash_map::const_iterator i = state_num.find(dst);
|
||||
for (succit->first(); !succit->done(); succit->next())
|
||||
{
|
||||
const state* dst = succit->dst();
|
||||
hash_map::const_iterator i = state_num.find(dst);
|
||||
|
||||
if (i == state_num.end()) // Ignore useless destinations.
|
||||
continue;
|
||||
if (i == state_num.end()) // Ignore useless destinations.
|
||||
continue;
|
||||
|
||||
bdd tgba_condition = bddtrue;
|
||||
is_initial_state = a->is_initial_state(dst);
|
||||
if (!a->get_artificial_initial_state() && is_initial_state)
|
||||
tgba_condition = a->get_state_condition(dst);
|
||||
bool is_accepting_state = a->is_accepting_state(dst);
|
||||
bool is_livelock_accepting_state =
|
||||
a->is_livelock_accepting_state(dst);
|
||||
bdd tgba_condition = bddtrue;
|
||||
is_initial_state = a->is_initial_state(dst);
|
||||
if (!a->get_artificial_initial_state() && is_initial_state)
|
||||
tgba_condition = a->get_state_condition(dst);
|
||||
bool is_accepting_state = a->is_accepting_state(dst);
|
||||
bool is_livelock_accepting_state =
|
||||
a->is_livelock_accepting_state(dst);
|
||||
|
||||
state_ta_explicit* new_dst =
|
||||
new state_ta_explicit
|
||||
(result_tgba->state_from_number(i->second),
|
||||
tgba_condition, is_initial_state,
|
||||
is_accepting_state,
|
||||
is_livelock_accepting_state);
|
||||
state_ta_explicit* new_dst =
|
||||
new state_ta_explicit
|
||||
(result_tgba->state_from_number(i->second),
|
||||
tgba_condition, is_initial_state,
|
||||
is_accepting_state,
|
||||
is_livelock_accepting_state);
|
||||
|
||||
state_ta_explicit* ta_dst = result->add_state(new_dst);
|
||||
state_ta_explicit* ta_dst = result->add_state(new_dst);
|
||||
|
||||
if (ta_dst != new_dst)
|
||||
{
|
||||
delete new_dst;
|
||||
}
|
||||
else if (a->get_artificial_initial_state())
|
||||
{
|
||||
if (a->get_artificial_initial_state() == dst)
|
||||
result->set_artificial_initial_state(new_dst);
|
||||
}
|
||||
if (ta_dst != new_dst)
|
||||
{
|
||||
delete new_dst;
|
||||
}
|
||||
else if (a->get_artificial_initial_state())
|
||||
{
|
||||
if (a->get_artificial_initial_state() == dst)
|
||||
result->set_artificial_initial_state(new_dst);
|
||||
}
|
||||
|
||||
else if (is_initial_state)
|
||||
result->add_to_initial_states_set(new_dst);
|
||||
else if (is_initial_state)
|
||||
result->add_to_initial_states_set(new_dst);
|
||||
|
||||
result->create_transition
|
||||
(ta_src, succit->cond(),
|
||||
succit->acc(),
|
||||
ta_dst);
|
||||
}
|
||||
delete succit;
|
||||
}
|
||||
result->create_transition
|
||||
(ta_src, succit->cond(),
|
||||
succit->acc(),
|
||||
ta_dst);
|
||||
}
|
||||
delete succit;
|
||||
}
|
||||
}
|
||||
|
||||
static partition_t
|
||||
|
|
@ -187,22 +187,22 @@ namespace spot
|
|||
unsigned num_sets = ta_->acc().num_sets();
|
||||
std::map<acc_cond::mark_t, bdd> m2b;
|
||||
int acc_vars = ta_->get_dict()->register_anonymous_variables(num_sets,
|
||||
&m2b);
|
||||
&m2b);
|
||||
auto mark_to_bdd = [&](acc_cond::mark_t m) -> bdd
|
||||
{
|
||||
auto i = m2b.find(m);
|
||||
if (i != m2b.end())
|
||||
return i->second;
|
||||
{
|
||||
auto i = m2b.find(m);
|
||||
if (i != m2b.end())
|
||||
return i->second;
|
||||
|
||||
bdd res = bddtrue;
|
||||
for (unsigned n = 0; n < num_sets; ++n)
|
||||
if (m.has(n))
|
||||
res &= bdd_ithvar(acc_vars + n);
|
||||
else
|
||||
res &= bdd_nithvar(acc_vars + n);
|
||||
m2b.emplace_hint(i, m, res);
|
||||
return res;
|
||||
};
|
||||
bdd res = bddtrue;
|
||||
for (unsigned n = 0; n < num_sets; ++n)
|
||||
if (m.has(n))
|
||||
res &= bdd_ithvar(acc_vars + n);
|
||||
else
|
||||
res &= bdd_nithvar(acc_vars + n);
|
||||
m2b.emplace_hint(i, m, res);
|
||||
return res;
|
||||
};
|
||||
|
||||
partition_t cur_run;
|
||||
partition_t next_run;
|
||||
|
|
@ -231,22 +231,22 @@ namespace spot
|
|||
auto artificial_initial_state = ta_->get_artificial_initial_state();
|
||||
|
||||
for (it = states_set.begin(); it != states_set.end(); ++it)
|
||||
{
|
||||
const state* s = *it;
|
||||
if (s == artificial_initial_state)
|
||||
I->insert(s);
|
||||
else if (!artificial_initial_state && ta_->is_initial_state(s))
|
||||
I->insert(s);
|
||||
else if (ta_->is_livelock_accepting_state(s)
|
||||
&& ta_->is_accepting_state(s))
|
||||
G_F->insert(s);
|
||||
else if (ta_->is_accepting_state(s))
|
||||
F->insert(s);
|
||||
else if (ta_->is_livelock_accepting_state(s))
|
||||
G->insert(s);
|
||||
else
|
||||
S->insert(s);
|
||||
}
|
||||
{
|
||||
const state* s = *it;
|
||||
if (s == artificial_initial_state)
|
||||
I->insert(s);
|
||||
else if (!artificial_initial_state && ta_->is_initial_state(s))
|
||||
I->insert(s);
|
||||
else if (ta_->is_livelock_accepting_state(s)
|
||||
&& ta_->is_accepting_state(s))
|
||||
G_F->insert(s);
|
||||
else if (ta_->is_accepting_state(s))
|
||||
F->insert(s);
|
||||
else if (ta_->is_livelock_accepting_state(s))
|
||||
G->insert(s);
|
||||
else
|
||||
S->insert(s);
|
||||
}
|
||||
|
||||
hash_map state_set_map;
|
||||
|
||||
|
|
@ -255,103 +255,103 @@ namespace spot
|
|||
// Use bdd variables to number sets. set_num is the first variable
|
||||
// available.
|
||||
unsigned set_num =
|
||||
ta_->get_dict()->register_anonymous_variables(size, &m2b);
|
||||
ta_->get_dict()->register_anonymous_variables(size, &m2b);
|
||||
|
||||
std::set<int> free_var;
|
||||
for (unsigned i = set_num; i < set_num + size; ++i)
|
||||
free_var.insert(i);
|
||||
free_var.insert(i);
|
||||
std::map<int, int> used_var;
|
||||
|
||||
for (hash_set::const_iterator i = I->begin(); i != I->end(); ++i)
|
||||
{
|
||||
hash_set* cI = new hash_set;
|
||||
cI->insert(*i);
|
||||
done.push_back(cI);
|
||||
{
|
||||
hash_set* cI = new hash_set;
|
||||
cI->insert(*i);
|
||||
done.push_back(cI);
|
||||
|
||||
used_var[set_num] = 1;
|
||||
free_var.erase(set_num);
|
||||
state_set_map[*i] = set_num;
|
||||
++set_num;
|
||||
used_var[set_num] = 1;
|
||||
free_var.erase(set_num);
|
||||
state_set_map[*i] = set_num;
|
||||
++set_num;
|
||||
|
||||
}
|
||||
}
|
||||
delete I;
|
||||
|
||||
if (!G->empty())
|
||||
{
|
||||
unsigned s = G->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(G);
|
||||
else
|
||||
done.push_back(G);
|
||||
for (hash_set::const_iterator i = G->begin(); i != G->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
{
|
||||
unsigned s = G->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(G);
|
||||
else
|
||||
done.push_back(G);
|
||||
for (hash_set::const_iterator i = G->begin(); i != G->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete G;
|
||||
}
|
||||
{
|
||||
delete G;
|
||||
}
|
||||
|
||||
if (!F->empty())
|
||||
{
|
||||
unsigned s = F->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(F);
|
||||
else
|
||||
done.push_back(F);
|
||||
for (hash_set::const_iterator i = F->begin(); i != F->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
{
|
||||
unsigned s = F->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(F);
|
||||
else
|
||||
done.push_back(F);
|
||||
for (hash_set::const_iterator i = F->begin(); i != F->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete F;
|
||||
}
|
||||
{
|
||||
delete F;
|
||||
}
|
||||
|
||||
if (!G_F->empty())
|
||||
{
|
||||
unsigned s = G_F->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(G_F);
|
||||
else
|
||||
done.push_back(G_F);
|
||||
for (hash_set::const_iterator i = G_F->begin(); i != G_F->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
{
|
||||
unsigned s = G_F->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(G_F);
|
||||
else
|
||||
done.push_back(G_F);
|
||||
for (hash_set::const_iterator i = G_F->begin(); i != G_F->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete G_F;
|
||||
}
|
||||
{
|
||||
delete G_F;
|
||||
}
|
||||
|
||||
if (!S->empty())
|
||||
{
|
||||
unsigned s = S->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(S);
|
||||
else
|
||||
done.push_back(S);
|
||||
for (hash_set::const_iterator i = S->begin(); i != S->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
{
|
||||
unsigned s = S->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(S);
|
||||
else
|
||||
done.push_back(S);
|
||||
for (hash_set::const_iterator i = S->begin(); i != S->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete S;
|
||||
}
|
||||
{
|
||||
delete S;
|
||||
}
|
||||
|
||||
|
||||
// A bdd_states_map is a list of formulae (in a BDD form)
|
||||
|
|
@ -366,132 +366,132 @@ namespace spot
|
|||
bdd bdd_false_acceptance_condition = bdd_ithvar(num);
|
||||
|
||||
while (did_split)
|
||||
{
|
||||
did_split = false;
|
||||
while (!cur_run.empty())
|
||||
{
|
||||
// Get a set to process.
|
||||
hash_set* cur = cur_run.front();
|
||||
cur_run.pop_front();
|
||||
{
|
||||
did_split = false;
|
||||
while (!cur_run.empty())
|
||||
{
|
||||
// Get a set to process.
|
||||
hash_set* cur = cur_run.front();
|
||||
cur_run.pop_front();
|
||||
|
||||
trace
|
||||
<< "processing " << format_hash_set(cur, ta_) << std::endl;
|
||||
trace
|
||||
<< "processing " << format_hash_set(cur, ta_) << std::endl;
|
||||
|
||||
hash_set::iterator hi;
|
||||
bdd_states_map bdd_map;
|
||||
for (hi = cur->begin(); hi != cur->end(); ++hi)
|
||||
{
|
||||
const state* src = *hi;
|
||||
bdd f = bddfalse;
|
||||
ta_succ_iterator* si = ta_->succ_iter(src);
|
||||
trace << "+src: " << src << std::endl;
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
const state* dst = si->dst();
|
||||
hash_map::const_iterator i = state_set_map.find(dst);
|
||||
hash_set::iterator hi;
|
||||
bdd_states_map bdd_map;
|
||||
for (hi = cur->begin(); hi != cur->end(); ++hi)
|
||||
{
|
||||
const state* src = *hi;
|
||||
bdd f = bddfalse;
|
||||
ta_succ_iterator* si = ta_->succ_iter(src);
|
||||
trace << "+src: " << src << std::endl;
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
const state* dst = si->dst();
|
||||
hash_map::const_iterator i = state_set_map.find(dst);
|
||||
|
||||
assert(i != state_set_map.end());
|
||||
auto curacc =
|
||||
mark_to_bdd(si->acc());
|
||||
f |= (bdd_ithvar(i->second)
|
||||
& si->cond() & curacc);
|
||||
trace
|
||||
<< "+f: " << bdd_format_accset(ta_->get_dict(), f)
|
||||
<< "\n -bdd_ithvar(i->second): "
|
||||
<< bdd_format_accset(ta_->get_dict(),
|
||||
bdd_ithvar(i->second))
|
||||
<< "\n -si->cond(): "
|
||||
<< bdd_format_accset(ta_->get_dict(),
|
||||
si->cond())
|
||||
<< "\n -current_acceptance_conditions: "
|
||||
<< si->acc()
|
||||
<< std::endl;
|
||||
}
|
||||
delete si;
|
||||
assert(i != state_set_map.end());
|
||||
auto curacc =
|
||||
mark_to_bdd(si->acc());
|
||||
f |= (bdd_ithvar(i->second)
|
||||
& si->cond() & curacc);
|
||||
trace
|
||||
<< "+f: " << bdd_format_accset(ta_->get_dict(), f)
|
||||
<< "\n -bdd_ithvar(i->second): "
|
||||
<< bdd_format_accset(ta_->get_dict(),
|
||||
bdd_ithvar(i->second))
|
||||
<< "\n -si->cond(): "
|
||||
<< bdd_format_accset(ta_->get_dict(),
|
||||
si->cond())
|
||||
<< "\n -current_acceptance_conditions: "
|
||||
<< si->acc()
|
||||
<< std::endl;
|
||||
}
|
||||
delete si;
|
||||
|
||||
// Have we already seen this formula ?
|
||||
bdd_states_map::iterator bsi = bdd_map.find(f);
|
||||
if (bsi == bdd_map.end())
|
||||
{
|
||||
// No, create a new set.
|
||||
hash_set* new_set = new hash_set;
|
||||
new_set->insert(src);
|
||||
bdd_map[f] = new_set;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Yes, add the current state to the set.
|
||||
bsi->second->insert(src);
|
||||
}
|
||||
}
|
||||
// Have we already seen this formula ?
|
||||
bdd_states_map::iterator bsi = bdd_map.find(f);
|
||||
if (bsi == bdd_map.end())
|
||||
{
|
||||
// No, create a new set.
|
||||
hash_set* new_set = new hash_set;
|
||||
new_set->insert(src);
|
||||
bdd_map[f] = new_set;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Yes, add the current state to the set.
|
||||
bsi->second->insert(src);
|
||||
}
|
||||
}
|
||||
|
||||
bdd_states_map::iterator bsi = bdd_map.begin();
|
||||
if (bdd_map.size() == 1)
|
||||
{
|
||||
// The set was not split.
|
||||
trace
|
||||
<< "set " << format_hash_set(bsi->second, ta_)
|
||||
<< " was not split" << std::endl;
|
||||
next_run.push_back(bsi->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
did_split = true;
|
||||
for (; bsi != bdd_map.end(); ++bsi)
|
||||
{
|
||||
hash_set* set = bsi->second;
|
||||
// Free the number associated to these states.
|
||||
unsigned num = state_set_map[*set->begin()];
|
||||
assert(used_var.find(num) != used_var.end());
|
||||
unsigned left = (used_var[num] -= set->size());
|
||||
// Make sure LEFT does not become negative
|
||||
// (hence bigger than SIZE when read as unsigned)
|
||||
assert(left < size);
|
||||
if (left == 0)
|
||||
{
|
||||
used_var.erase(num);
|
||||
free_var.insert(num);
|
||||
}
|
||||
// Pick a free number
|
||||
assert(!free_var.empty());
|
||||
num = *free_var.begin();
|
||||
free_var.erase(free_var.begin());
|
||||
used_var[num] = set->size();
|
||||
for (hash_set::iterator hit = set->begin();
|
||||
hit != set->end(); ++hit)
|
||||
state_set_map[*hit] = num;
|
||||
// Trivial sets can't be splitted any further.
|
||||
if (set->size() == 1)
|
||||
{
|
||||
trace
|
||||
<< "set " << format_hash_set(set, ta_)
|
||||
<< " is minimal" << std::endl;
|
||||
done.push_back(set);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace
|
||||
<< "set " << format_hash_set(set, ta_)
|
||||
<< " should be processed further" << std::endl;
|
||||
next_run.push_back(set);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete cur;
|
||||
}
|
||||
if (did_split)
|
||||
trace
|
||||
<< "splitting did occur during this pass." << std::endl;
|
||||
bdd_states_map::iterator bsi = bdd_map.begin();
|
||||
if (bdd_map.size() == 1)
|
||||
{
|
||||
// The set was not split.
|
||||
trace
|
||||
<< "set " << format_hash_set(bsi->second, ta_)
|
||||
<< " was not split" << std::endl;
|
||||
next_run.push_back(bsi->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
did_split = true;
|
||||
for (; bsi != bdd_map.end(); ++bsi)
|
||||
{
|
||||
hash_set* set = bsi->second;
|
||||
// Free the number associated to these states.
|
||||
unsigned num = state_set_map[*set->begin()];
|
||||
assert(used_var.find(num) != used_var.end());
|
||||
unsigned left = (used_var[num] -= set->size());
|
||||
// Make sure LEFT does not become negative
|
||||
// (hence bigger than SIZE when read as unsigned)
|
||||
assert(left < size);
|
||||
if (left == 0)
|
||||
{
|
||||
used_var.erase(num);
|
||||
free_var.insert(num);
|
||||
}
|
||||
// Pick a free number
|
||||
assert(!free_var.empty());
|
||||
num = *free_var.begin();
|
||||
free_var.erase(free_var.begin());
|
||||
used_var[num] = set->size();
|
||||
for (hash_set::iterator hit = set->begin();
|
||||
hit != set->end(); ++hit)
|
||||
state_set_map[*hit] = num;
|
||||
// Trivial sets can't be splitted any further.
|
||||
if (set->size() == 1)
|
||||
{
|
||||
trace
|
||||
<< "set " << format_hash_set(set, ta_)
|
||||
<< " is minimal" << std::endl;
|
||||
done.push_back(set);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace
|
||||
<< "set " << format_hash_set(set, ta_)
|
||||
<< " should be processed further" << std::endl;
|
||||
next_run.push_back(set);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete cur;
|
||||
}
|
||||
if (did_split)
|
||||
trace
|
||||
<< "splitting did occur during this pass." << std::endl;
|
||||
|
||||
std::swap(cur_run, next_run);
|
||||
}
|
||||
std::swap(cur_run, next_run);
|
||||
}
|
||||
|
||||
done.splice(done.end(), cur_run);
|
||||
|
||||
#ifdef TRACE
|
||||
trace << "Final partition: ";
|
||||
for (partition_t::const_iterator i = done.begin(); i != done.end(); ++i)
|
||||
trace << format_hash_set(*i, ta_) << ' ';
|
||||
trace << format_hash_set(*i, ta_) << ' ';
|
||||
trace << std::endl;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -51,17 +51,17 @@ namespace spot
|
|||
{
|
||||
|
||||
if (artificial_livelock_acc_state)
|
||||
{
|
||||
auto artificial_livelock_acc_state_added =
|
||||
{
|
||||
auto artificial_livelock_acc_state_added =
|
||||
testing_automata->add_state(artificial_livelock_acc_state);
|
||||
|
||||
// unique artificial_livelock_acc_state
|
||||
assert(artificial_livelock_acc_state_added
|
||||
== artificial_livelock_acc_state);
|
||||
(void)artificial_livelock_acc_state_added;
|
||||
artificial_livelock_acc_state->set_livelock_accepting_state(true);
|
||||
artificial_livelock_acc_state->free_transitions();
|
||||
}
|
||||
// unique artificial_livelock_acc_state
|
||||
assert(artificial_livelock_acc_state_added
|
||||
== artificial_livelock_acc_state);
|
||||
(void)artificial_livelock_acc_state_added;
|
||||
artificial_livelock_acc_state->set_livelock_accepting_state(true);
|
||||
artificial_livelock_acc_state->free_transitions();
|
||||
}
|
||||
|
||||
ta::states_set_t states_set = testing_automata->get_states_set();
|
||||
ta::states_set_t::iterator it;
|
||||
|
|
@ -70,86 +70,86 @@ namespace spot
|
|||
new state_ta_explicit::transitions;
|
||||
|
||||
for (it = states_set.begin(); it != states_set.end(); ++it)
|
||||
{
|
||||
auto source = const_cast<state_ta_explicit*>
|
||||
(static_cast<const state_ta_explicit*>(*it));
|
||||
{
|
||||
auto source = const_cast<state_ta_explicit*>
|
||||
(static_cast<const state_ta_explicit*>(*it));
|
||||
|
||||
transitions_to_livelock_states->clear();
|
||||
transitions_to_livelock_states->clear();
|
||||
|
||||
state_ta_explicit::transitions* trans = source->get_transitions();
|
||||
state_ta_explicit::transitions::iterator it_trans;
|
||||
state_ta_explicit::transitions* trans = source->get_transitions();
|
||||
state_ta_explicit::transitions::iterator it_trans;
|
||||
|
||||
if (trans)
|
||||
for (it_trans = trans->begin(); it_trans != trans->end();)
|
||||
{
|
||||
auto dest = const_cast<state_ta_explicit*>((*it_trans)->dest);
|
||||
if (trans)
|
||||
for (it_trans = trans->begin(); it_trans != trans->end();)
|
||||
{
|
||||
auto dest = const_cast<state_ta_explicit*>((*it_trans)->dest);
|
||||
|
||||
state_ta_explicit::transitions* dest_trans =
|
||||
dest->get_transitions();
|
||||
bool dest_trans_empty = !dest_trans || dest_trans->empty();
|
||||
state_ta_explicit::transitions* dest_trans =
|
||||
dest->get_transitions();
|
||||
bool dest_trans_empty = !dest_trans || dest_trans->empty();
|
||||
|
||||
//select transitions where a destination is a livelock state
|
||||
// which isn't a Buchi accepting state and has successors
|
||||
if (dest->is_livelock_accepting_state()
|
||||
&& (!dest->is_accepting_state()) && (!dest_trans_empty))
|
||||
transitions_to_livelock_states->push_front(*it_trans);
|
||||
//select transitions where a destination is a livelock state
|
||||
// which isn't a Buchi accepting state and has successors
|
||||
if (dest->is_livelock_accepting_state()
|
||||
&& (!dest->is_accepting_state()) && (!dest_trans_empty))
|
||||
transitions_to_livelock_states->push_front(*it_trans);
|
||||
|
||||
// optimization to have, after minimization, an unique
|
||||
// livelock state which has no successors
|
||||
if (dest->is_livelock_accepting_state() && (dest_trans_empty))
|
||||
dest->set_accepting_state(false);
|
||||
// optimization to have, after minimization, an unique
|
||||
// livelock state which has no successors
|
||||
if (dest->is_livelock_accepting_state() && (dest_trans_empty))
|
||||
dest->set_accepting_state(false);
|
||||
|
||||
++it_trans;
|
||||
}
|
||||
++it_trans;
|
||||
}
|
||||
|
||||
if (transitions_to_livelock_states)
|
||||
{
|
||||
state_ta_explicit::transitions::iterator it_trans;
|
||||
if (transitions_to_livelock_states)
|
||||
{
|
||||
state_ta_explicit::transitions::iterator it_trans;
|
||||
|
||||
for (it_trans = transitions_to_livelock_states->begin();
|
||||
it_trans != transitions_to_livelock_states->end();
|
||||
++it_trans)
|
||||
{
|
||||
if (artificial_livelock_acc_state)
|
||||
{
|
||||
testing_automata->create_transition
|
||||
(source,
|
||||
(*it_trans)->condition,
|
||||
(*it_trans)->acceptance_conditions,
|
||||
artificial_livelock_acc_state, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
testing_automata->create_transition
|
||||
(source,
|
||||
(*it_trans)->condition,
|
||||
(*it_trans)->acceptance_conditions,
|
||||
((*it_trans)->dest)->stuttering_reachable_livelock,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (it_trans = transitions_to_livelock_states->begin();
|
||||
it_trans != transitions_to_livelock_states->end();
|
||||
++it_trans)
|
||||
{
|
||||
if (artificial_livelock_acc_state)
|
||||
{
|
||||
testing_automata->create_transition
|
||||
(source,
|
||||
(*it_trans)->condition,
|
||||
(*it_trans)->acceptance_conditions,
|
||||
artificial_livelock_acc_state, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
testing_automata->create_transition
|
||||
(source,
|
||||
(*it_trans)->condition,
|
||||
(*it_trans)->acceptance_conditions,
|
||||
((*it_trans)->dest)->stuttering_reachable_livelock,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete transitions_to_livelock_states;
|
||||
|
||||
for (it = states_set.begin(); it != states_set.end(); ++it)
|
||||
{
|
||||
state_ta_explicit* state = static_cast<state_ta_explicit*> (*it);
|
||||
state_ta_explicit::transitions* state_trans =
|
||||
{
|
||||
state_ta_explicit* state = static_cast<state_ta_explicit*> (*it);
|
||||
state_ta_explicit::transitions* state_trans =
|
||||
(state)->get_transitions();
|
||||
bool state_trans_empty = !state_trans || state_trans->empty();
|
||||
bool state_trans_empty = !state_trans || state_trans->empty();
|
||||
|
||||
if (state->is_livelock_accepting_state()
|
||||
&& (!state->is_accepting_state()) && (!state_trans_empty))
|
||||
state->set_livelock_accepting_state(false);
|
||||
}
|
||||
if (state->is_livelock_accepting_state()
|
||||
&& (!state->is_accepting_state()) && (!state_trans_empty))
|
||||
state->set_livelock_accepting_state(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
compute_livelock_acceptance_states(const ta_explicit_ptr& testing_aut,
|
||||
bool single_pass_emptiness_check,
|
||||
state_ta_explicit*
|
||||
artificial_livelock_acc_state)
|
||||
bool single_pass_emptiness_check,
|
||||
state_ta_explicit*
|
||||
artificial_livelock_acc_state)
|
||||
{
|
||||
// We use five main data in this algorithm:
|
||||
// * sscc: a stack of strongly stuttering-connected components (SSCC)
|
||||
|
|
@ -177,234 +177,234 @@ namespace spot
|
|||
std::stack<const state*> init_set;
|
||||
|
||||
for (auto s: testing_aut->get_initial_states_set())
|
||||
init_set.push(s);
|
||||
init_set.push(s);
|
||||
|
||||
while (!init_set.empty())
|
||||
{
|
||||
// Setup depth-first search from initial states.
|
||||
{
|
||||
// Setup depth-first search from initial states.
|
||||
|
||||
{
|
||||
auto init = down_cast<const state_ta_explicit*> (init_set.top());
|
||||
init_set.pop();
|
||||
{
|
||||
auto init = down_cast<const state_ta_explicit*> (init_set.top());
|
||||
init_set.pop();
|
||||
|
||||
if (!h.emplace(init, num + 1).second)
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
if (!h.emplace(init, num + 1).second)
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
|
||||
sscc.push(++num);
|
||||
arc.push(0U);
|
||||
sscc.top().is_accepting
|
||||
sscc.push(++num);
|
||||
arc.push(0U);
|
||||
sscc.top().is_accepting
|
||||
= testing_aut->is_accepting_state(init);
|
||||
twa_succ_iterator* iter = testing_aut->succ_iter(init);
|
||||
iter->first();
|
||||
todo.emplace(init, iter);
|
||||
}
|
||||
twa_succ_iterator* iter = testing_aut->succ_iter(init);
|
||||
iter->first();
|
||||
todo.emplace(init, iter);
|
||||
}
|
||||
|
||||
while (!todo.empty())
|
||||
{
|
||||
auto curr = todo.top().first;
|
||||
while (!todo.empty())
|
||||
{
|
||||
auto curr = todo.top().first;
|
||||
|
||||
auto i = h.find(curr);
|
||||
// If we have reached a dead component, ignore it.
|
||||
if (i != h.end() && i->second == -1)
|
||||
{
|
||||
todo.pop();
|
||||
continue;
|
||||
}
|
||||
auto i = h.find(curr);
|
||||
// If we have reached a dead component, ignore it.
|
||||
if (i != h.end() && i->second == -1)
|
||||
{
|
||||
todo.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
// We are looking at the next successor in SUCC.
|
||||
twa_succ_iterator* succ = todo.top().second;
|
||||
// We are looking at the next successor in SUCC.
|
||||
twa_succ_iterator* succ = todo.top().second;
|
||||
|
||||
// If there is no more successor, backtrack.
|
||||
if (succ->done())
|
||||
{
|
||||
// We have explored all successors of state CURR.
|
||||
// If there is no more successor, backtrack.
|
||||
if (succ->done())
|
||||
{
|
||||
// We have explored all successors of state CURR.
|
||||
|
||||
// Backtrack TODO.
|
||||
todo.pop();
|
||||
// Backtrack TODO.
|
||||
todo.pop();
|
||||
|
||||
// fill rem with any component removed,
|
||||
assert(i != h.end());
|
||||
sscc.rem().push_front(curr);
|
||||
// fill rem with any component removed,
|
||||
assert(i != h.end());
|
||||
sscc.rem().push_front(curr);
|
||||
|
||||
// When backtracking the root of an SSCC, we must also
|
||||
// remove that SSCC from the ROOT stacks. We must
|
||||
// discard from H all reachable states from this SSCC.
|
||||
assert(!sscc.empty());
|
||||
if (sscc.top().index == i->second)
|
||||
{
|
||||
// removing states
|
||||
bool is_livelock_accepting_sscc = (sscc.rem().size() > 1)
|
||||
&& ((sscc.top().is_accepting) ||
|
||||
(testing_aut->acc().
|
||||
accepting(sscc.top().condition)));
|
||||
trace << "*** sscc.size() = ***" << sscc.size() << '\n';
|
||||
for (auto j: sscc.rem())
|
||||
{
|
||||
h[j] = -1;
|
||||
// When backtracking the root of an SSCC, we must also
|
||||
// remove that SSCC from the ROOT stacks. We must
|
||||
// discard from H all reachable states from this SSCC.
|
||||
assert(!sscc.empty());
|
||||
if (sscc.top().index == i->second)
|
||||
{
|
||||
// removing states
|
||||
bool is_livelock_accepting_sscc = (sscc.rem().size() > 1)
|
||||
&& ((sscc.top().is_accepting) ||
|
||||
(testing_aut->acc().
|
||||
accepting(sscc.top().condition)));
|
||||
trace << "*** sscc.size() = ***" << sscc.size() << '\n';
|
||||
for (auto j: sscc.rem())
|
||||
{
|
||||
h[j] = -1;
|
||||
|
||||
if (is_livelock_accepting_sscc)
|
||||
{
|
||||
// if it is an accepting sscc add the state to
|
||||
// G (=the livelock-accepting states set)
|
||||
trace << "*** sscc.size() > 1: states: ***"
|
||||
<< testing_aut->format_state(j)
|
||||
<< '\n';
|
||||
auto livelock_accepting_state =
|
||||
const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(j));
|
||||
if (is_livelock_accepting_sscc)
|
||||
{
|
||||
// if it is an accepting sscc add the state to
|
||||
// G (=the livelock-accepting states set)
|
||||
trace << "*** sscc.size() > 1: states: ***"
|
||||
<< testing_aut->format_state(j)
|
||||
<< '\n';
|
||||
auto livelock_accepting_state =
|
||||
const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(j));
|
||||
|
||||
livelock_accepting_state->
|
||||
set_livelock_accepting_state(true);
|
||||
livelock_accepting_state->
|
||||
set_livelock_accepting_state(true);
|
||||
|
||||
if (single_pass_emptiness_check)
|
||||
{
|
||||
livelock_accepting_state
|
||||
->set_accepting_state(true);
|
||||
livelock_accepting_state
|
||||
->stuttering_reachable_livelock
|
||||
= livelock_accepting_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (single_pass_emptiness_check)
|
||||
{
|
||||
livelock_accepting_state
|
||||
->set_accepting_state(true);
|
||||
livelock_accepting_state
|
||||
->stuttering_reachable_livelock
|
||||
= livelock_accepting_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(!arc.empty());
|
||||
sscc.pop();
|
||||
arc.pop();
|
||||
}
|
||||
assert(!arc.empty());
|
||||
sscc.pop();
|
||||
arc.pop();
|
||||
}
|
||||
|
||||
// automata reduction
|
||||
testing_aut->delete_stuttering_and_hole_successors(curr);
|
||||
// automata reduction
|
||||
testing_aut->delete_stuttering_and_hole_successors(curr);
|
||||
|
||||
delete succ;
|
||||
// Do not delete CURR: it is a key in H.
|
||||
continue;
|
||||
}
|
||||
delete succ;
|
||||
// Do not delete CURR: it is a key in H.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fetch the values destination state we are interested in...
|
||||
auto dest = succ->dst();
|
||||
// Fetch the values destination state we are interested in...
|
||||
auto dest = succ->dst();
|
||||
|
||||
auto acc_cond = succ->acc();
|
||||
// ... and point the iterator to the next successor, for
|
||||
// the next iteration.
|
||||
succ->next();
|
||||
// We do not need SUCC from now on.
|
||||
auto acc_cond = succ->acc();
|
||||
// ... and point the iterator to the next successor, for
|
||||
// the next iteration.
|
||||
succ->next();
|
||||
// We do not need SUCC from now on.
|
||||
|
||||
// Are we going to a new state through a stuttering transition?
|
||||
bool is_stuttering_transition =
|
||||
testing_aut->get_state_condition(curr)
|
||||
== testing_aut->get_state_condition(dest);
|
||||
auto id = h.find(dest);
|
||||
// Are we going to a new state through a stuttering transition?
|
||||
bool is_stuttering_transition =
|
||||
testing_aut->get_state_condition(curr)
|
||||
== testing_aut->get_state_condition(dest);
|
||||
auto id = h.find(dest);
|
||||
|
||||
// Is this a new state?
|
||||
if (id == h.end())
|
||||
{
|
||||
if (!is_stuttering_transition)
|
||||
{
|
||||
init_set.push(dest);
|
||||
dest->destroy();
|
||||
continue;
|
||||
}
|
||||
// Is this a new state?
|
||||
if (id == h.end())
|
||||
{
|
||||
if (!is_stuttering_transition)
|
||||
{
|
||||
init_set.push(dest);
|
||||
dest->destroy();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Number it, stack it, and register its successors
|
||||
// for later processing.
|
||||
h[dest] = ++num;
|
||||
sscc.push(num);
|
||||
arc.push(acc_cond);
|
||||
sscc.top().is_accepting =
|
||||
testing_aut->is_accepting_state(dest);
|
||||
// Number it, stack it, and register its successors
|
||||
// for later processing.
|
||||
h[dest] = ++num;
|
||||
sscc.push(num);
|
||||
arc.push(acc_cond);
|
||||
sscc.top().is_accepting =
|
||||
testing_aut->is_accepting_state(dest);
|
||||
|
||||
twa_succ_iterator* iter = testing_aut->succ_iter(dest);
|
||||
iter->first();
|
||||
todo.emplace(dest, iter);
|
||||
continue;
|
||||
}
|
||||
dest->destroy();
|
||||
twa_succ_iterator* iter = testing_aut->succ_iter(dest);
|
||||
iter->first();
|
||||
todo.emplace(dest, iter);
|
||||
continue;
|
||||
}
|
||||
dest->destroy();
|
||||
|
||||
// If we have reached a dead component, ignore it.
|
||||
if (id->second == -1)
|
||||
continue;
|
||||
// If we have reached a dead component, ignore it.
|
||||
if (id->second == -1)
|
||||
continue;
|
||||
|
||||
trace << "***compute_livelock_acceptance_states: CYCLE***\n";
|
||||
trace << "***compute_livelock_acceptance_states: CYCLE***\n";
|
||||
|
||||
if (!curr->compare(id->first))
|
||||
{
|
||||
auto self_loop_state = const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(curr));
|
||||
assert(self_loop_state);
|
||||
if (!curr->compare(id->first))
|
||||
{
|
||||
auto self_loop_state = const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(curr));
|
||||
assert(self_loop_state);
|
||||
|
||||
if (testing_aut->is_accepting_state(self_loop_state)
|
||||
|| (testing_aut->acc().accepting(acc_cond)))
|
||||
{
|
||||
self_loop_state->set_livelock_accepting_state(true);
|
||||
if (single_pass_emptiness_check)
|
||||
{
|
||||
self_loop_state->set_accepting_state(true);
|
||||
self_loop_state->stuttering_reachable_livelock
|
||||
= self_loop_state;
|
||||
}
|
||||
}
|
||||
if (testing_aut->is_accepting_state(self_loop_state)
|
||||
|| (testing_aut->acc().accepting(acc_cond)))
|
||||
{
|
||||
self_loop_state->set_livelock_accepting_state(true);
|
||||
if (single_pass_emptiness_check)
|
||||
{
|
||||
self_loop_state->set_accepting_state(true);
|
||||
self_loop_state->stuttering_reachable_livelock
|
||||
= self_loop_state;
|
||||
}
|
||||
}
|
||||
|
||||
trace
|
||||
<< "***compute_livelock_acceptance_states: CYCLE: "
|
||||
<< "self_loop_state***\n";
|
||||
}
|
||||
trace
|
||||
<< "***compute_livelock_acceptance_states: CYCLE: "
|
||||
<< "self_loop_state***\n";
|
||||
}
|
||||
|
||||
// Now this is the most interesting case. We have reached a
|
||||
// state S1 which is already part of a non-dead SSCC. Any such
|
||||
// non-dead SSCC has necessarily been crossed by our path to
|
||||
// this state: there is a state S2 in our path which belongs
|
||||
// to this SSCC too. We are going to merge all states between
|
||||
// this S1 and S2 into this SSCC.
|
||||
//
|
||||
// This merge is easy to do because the order of the SSCC in
|
||||
// ROOT is ascending: we just have to merge all SSCCs from the
|
||||
// top of ROOT that have an index greater to the one of
|
||||
// the SSCC of S2 (called the "threshold").
|
||||
int threshold = id->second;
|
||||
std::list<const state*> rem;
|
||||
bool acc = false;
|
||||
// Now this is the most interesting case. We have reached a
|
||||
// state S1 which is already part of a non-dead SSCC. Any such
|
||||
// non-dead SSCC has necessarily been crossed by our path to
|
||||
// this state: there is a state S2 in our path which belongs
|
||||
// to this SSCC too. We are going to merge all states between
|
||||
// this S1 and S2 into this SSCC.
|
||||
//
|
||||
// This merge is easy to do because the order of the SSCC in
|
||||
// ROOT is ascending: we just have to merge all SSCCs from the
|
||||
// top of ROOT that have an index greater to the one of
|
||||
// the SSCC of S2 (called the "threshold").
|
||||
int threshold = id->second;
|
||||
std::list<const state*> rem;
|
||||
bool acc = false;
|
||||
|
||||
while (threshold < sscc.top().index)
|
||||
{
|
||||
assert(!sscc.empty());
|
||||
assert(!arc.empty());
|
||||
acc |= sscc.top().is_accepting;
|
||||
acc_cond |= sscc.top().condition;
|
||||
acc_cond |= arc.top();
|
||||
rem.splice(rem.end(), sscc.rem());
|
||||
sscc.pop();
|
||||
arc.pop();
|
||||
}
|
||||
while (threshold < sscc.top().index)
|
||||
{
|
||||
assert(!sscc.empty());
|
||||
assert(!arc.empty());
|
||||
acc |= sscc.top().is_accepting;
|
||||
acc_cond |= sscc.top().condition;
|
||||
acc_cond |= arc.top();
|
||||
rem.splice(rem.end(), sscc.rem());
|
||||
sscc.pop();
|
||||
arc.pop();
|
||||
}
|
||||
|
||||
// Note that we do not always have
|
||||
// threshold == sscc.top().index
|
||||
// after this loop, the SSCC whose index is threshold might have
|
||||
// been merged with a lower SSCC.
|
||||
// Note that we do not always have
|
||||
// threshold == sscc.top().index
|
||||
// after this loop, the SSCC whose index is threshold might have
|
||||
// been merged with a lower SSCC.
|
||||
|
||||
// Accumulate all acceptance conditions into the merged SSCC.
|
||||
sscc.top().is_accepting |= acc;
|
||||
sscc.top().condition |= acc_cond;
|
||||
// Accumulate all acceptance conditions into the merged SSCC.
|
||||
sscc.top().is_accepting |= acc;
|
||||
sscc.top().condition |= acc_cond;
|
||||
|
||||
sscc.rem().splice(sscc.rem().end(), rem);
|
||||
sscc.rem().splice(sscc.rem().end(), rem);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (artificial_livelock_acc_state || single_pass_emptiness_check)
|
||||
transform_to_single_pass_automaton(testing_aut,
|
||||
artificial_livelock_acc_state);
|
||||
transform_to_single_pass_automaton(testing_aut,
|
||||
artificial_livelock_acc_state);
|
||||
}
|
||||
|
||||
ta_explicit_ptr
|
||||
build_ta(const ta_explicit_ptr& ta, bdd atomic_propositions_set_,
|
||||
bool degeneralized,
|
||||
bool single_pass_emptiness_check,
|
||||
bool artificial_livelock_state_mode,
|
||||
bool no_livelock)
|
||||
bool degeneralized,
|
||||
bool single_pass_emptiness_check,
|
||||
bool artificial_livelock_state_mode,
|
||||
bool no_livelock)
|
||||
{
|
||||
|
||||
std::stack<state_ta_explicit*> todo;
|
||||
|
|
@ -414,140 +414,140 @@ namespace spot
|
|||
auto tgba_init_state = tgba_->get_init_state();
|
||||
|
||||
bdd tgba_condition = [&]()
|
||||
{
|
||||
bdd cond = bddfalse;
|
||||
for (auto i: tgba_->succ(tgba_init_state))
|
||||
cond |= i->cond();
|
||||
return cond;
|
||||
}();
|
||||
{
|
||||
bdd cond = bddfalse;
|
||||
for (auto i: tgba_->succ(tgba_init_state))
|
||||
cond |= i->cond();
|
||||
return cond;
|
||||
}();
|
||||
|
||||
bool is_acc = false;
|
||||
if (degeneralized)
|
||||
{
|
||||
twa_succ_iterator* it = tgba_->succ_iter(tgba_init_state);
|
||||
it->first();
|
||||
if (!it->done())
|
||||
is_acc = it->acc() != 0U;
|
||||
delete it;
|
||||
}
|
||||
{
|
||||
twa_succ_iterator* it = tgba_->succ_iter(tgba_init_state);
|
||||
it->first();
|
||||
if (!it->done())
|
||||
is_acc = it->acc() != 0U;
|
||||
delete it;
|
||||
}
|
||||
|
||||
bdd satone_tgba_condition;
|
||||
while ((satone_tgba_condition = bdd_satoneset(tgba_condition,
|
||||
atomic_propositions_set_,
|
||||
bddtrue)) != bddfalse)
|
||||
{
|
||||
tgba_condition -= satone_tgba_condition;
|
||||
state_ta_explicit* init_state = new
|
||||
state_ta_explicit(tgba_init_state->clone(),
|
||||
satone_tgba_condition, true, is_acc);
|
||||
state_ta_explicit* s = ta->add_state(init_state);
|
||||
assert(s == init_state);
|
||||
ta->add_to_initial_states_set(s);
|
||||
atomic_propositions_set_,
|
||||
bddtrue)) != bddfalse)
|
||||
{
|
||||
tgba_condition -= satone_tgba_condition;
|
||||
state_ta_explicit* init_state = new
|
||||
state_ta_explicit(tgba_init_state->clone(),
|
||||
satone_tgba_condition, true, is_acc);
|
||||
state_ta_explicit* s = ta->add_state(init_state);
|
||||
assert(s == init_state);
|
||||
ta->add_to_initial_states_set(s);
|
||||
|
||||
todo.push(init_state);
|
||||
}
|
||||
todo.push(init_state);
|
||||
}
|
||||
tgba_init_state->destroy();
|
||||
|
||||
while (!todo.empty())
|
||||
{
|
||||
state_ta_explicit* source = todo.top();
|
||||
todo.pop();
|
||||
{
|
||||
state_ta_explicit* source = todo.top();
|
||||
todo.pop();
|
||||
|
||||
twa_succ_iterator* twa_succ_it =
|
||||
tgba_->succ_iter(source->get_tgba_state());
|
||||
for (twa_succ_it->first(); !twa_succ_it->done();
|
||||
twa_succ_it->next())
|
||||
{
|
||||
const state* tgba_state = twa_succ_it->dst();
|
||||
bdd tgba_condition = twa_succ_it->cond();
|
||||
acc_cond::mark_t tgba_acceptance_conditions =
|
||||
twa_succ_iterator* twa_succ_it =
|
||||
tgba_->succ_iter(source->get_tgba_state());
|
||||
for (twa_succ_it->first(); !twa_succ_it->done();
|
||||
twa_succ_it->next())
|
||||
{
|
||||
const state* tgba_state = twa_succ_it->dst();
|
||||
bdd tgba_condition = twa_succ_it->cond();
|
||||
acc_cond::mark_t tgba_acceptance_conditions =
|
||||
twa_succ_it->acc();
|
||||
bdd satone_tgba_condition;
|
||||
while ((satone_tgba_condition =
|
||||
bdd_satoneset(tgba_condition,
|
||||
atomic_propositions_set_, bddtrue))
|
||||
!= bddfalse)
|
||||
{
|
||||
tgba_condition -= satone_tgba_condition;
|
||||
bdd satone_tgba_condition;
|
||||
while ((satone_tgba_condition =
|
||||
bdd_satoneset(tgba_condition,
|
||||
atomic_propositions_set_, bddtrue))
|
||||
!= bddfalse)
|
||||
{
|
||||
tgba_condition -= satone_tgba_condition;
|
||||
|
||||
bdd all_props = bddtrue;
|
||||
bdd dest_condition;
|
||||
bdd all_props = bddtrue;
|
||||
bdd dest_condition;
|
||||
|
||||
bool is_acc = false;
|
||||
if (degeneralized)
|
||||
{
|
||||
twa_succ_iterator* it = tgba_->succ_iter(tgba_state);
|
||||
it->first();
|
||||
if (!it->done())
|
||||
is_acc = it->acc() != 0U;
|
||||
delete it;
|
||||
}
|
||||
bool is_acc = false;
|
||||
if (degeneralized)
|
||||
{
|
||||
twa_succ_iterator* it = tgba_->succ_iter(tgba_state);
|
||||
it->first();
|
||||
if (!it->done())
|
||||
is_acc = it->acc() != 0U;
|
||||
delete it;
|
||||
}
|
||||
|
||||
if (satone_tgba_condition == source->get_tgba_condition())
|
||||
while ((dest_condition =
|
||||
bdd_satoneset(all_props,
|
||||
atomic_propositions_set_, bddtrue))
|
||||
!= bddfalse)
|
||||
{
|
||||
all_props -= dest_condition;
|
||||
state_ta_explicit* new_dest =
|
||||
new state_ta_explicit(tgba_state->clone(),
|
||||
dest_condition, false, is_acc);
|
||||
state_ta_explicit* dest = ta->add_state(new_dest);
|
||||
if (satone_tgba_condition == source->get_tgba_condition())
|
||||
while ((dest_condition =
|
||||
bdd_satoneset(all_props,
|
||||
atomic_propositions_set_, bddtrue))
|
||||
!= bddfalse)
|
||||
{
|
||||
all_props -= dest_condition;
|
||||
state_ta_explicit* new_dest =
|
||||
new state_ta_explicit(tgba_state->clone(),
|
||||
dest_condition, false, is_acc);
|
||||
state_ta_explicit* dest = ta->add_state(new_dest);
|
||||
|
||||
if (dest != new_dest)
|
||||
{
|
||||
// the state dest already exists in the automaton
|
||||
new_dest->get_tgba_state()->destroy();
|
||||
delete new_dest;
|
||||
}
|
||||
else
|
||||
{
|
||||
todo.push(dest);
|
||||
}
|
||||
if (dest != new_dest)
|
||||
{
|
||||
// the state dest already exists in the automaton
|
||||
new_dest->get_tgba_state()->destroy();
|
||||
delete new_dest;
|
||||
}
|
||||
else
|
||||
{
|
||||
todo.push(dest);
|
||||
}
|
||||
|
||||
bdd cs = bdd_setxor(source->get_tgba_condition(),
|
||||
dest->get_tgba_condition());
|
||||
ta->create_transition(source, cs,
|
||||
tgba_acceptance_conditions, dest);
|
||||
}
|
||||
}
|
||||
tgba_state->destroy();
|
||||
}
|
||||
delete twa_succ_it;
|
||||
}
|
||||
bdd cs = bdd_setxor(source->get_tgba_condition(),
|
||||
dest->get_tgba_condition());
|
||||
ta->create_transition(source, cs,
|
||||
tgba_acceptance_conditions, dest);
|
||||
}
|
||||
}
|
||||
tgba_state->destroy();
|
||||
}
|
||||
delete twa_succ_it;
|
||||
}
|
||||
|
||||
if (no_livelock)
|
||||
return ta;
|
||||
return ta;
|
||||
|
||||
state_ta_explicit* artificial_livelock_acc_state = nullptr;
|
||||
|
||||
trace << "*** build_ta: artificial_livelock_acc_state_mode = ***"
|
||||
<< artificial_livelock_state_mode << std::endl;
|
||||
<< artificial_livelock_state_mode << std::endl;
|
||||
|
||||
if (artificial_livelock_state_mode)
|
||||
{
|
||||
single_pass_emptiness_check = true;
|
||||
artificial_livelock_acc_state =
|
||||
new state_ta_explicit(ta->get_tgba()->get_init_state(), bddtrue,
|
||||
false, false, true, nullptr);
|
||||
trace
|
||||
<< "*** build_ta: artificial_livelock_acc_state = ***"
|
||||
<< artificial_livelock_acc_state << std::endl;
|
||||
}
|
||||
{
|
||||
single_pass_emptiness_check = true;
|
||||
artificial_livelock_acc_state =
|
||||
new state_ta_explicit(ta->get_tgba()->get_init_state(), bddtrue,
|
||||
false, false, true, nullptr);
|
||||
trace
|
||||
<< "*** build_ta: artificial_livelock_acc_state = ***"
|
||||
<< artificial_livelock_acc_state << std::endl;
|
||||
}
|
||||
|
||||
compute_livelock_acceptance_states(ta, single_pass_emptiness_check,
|
||||
artificial_livelock_acc_state);
|
||||
artificial_livelock_acc_state);
|
||||
return ta;
|
||||
}
|
||||
}
|
||||
|
||||
ta_explicit_ptr
|
||||
tgba_to_ta(const const_twa_ptr& tgba_, bdd atomic_propositions_set_,
|
||||
bool degeneralized, bool artificial_initial_state_mode,
|
||||
bool single_pass_emptiness_check,
|
||||
bool artificial_livelock_state_mode,
|
||||
bool no_livelock)
|
||||
bool degeneralized, bool artificial_initial_state_mode,
|
||||
bool single_pass_emptiness_check,
|
||||
bool artificial_livelock_state_mode,
|
||||
bool no_livelock)
|
||||
{
|
||||
ta_explicit_ptr ta;
|
||||
|
||||
|
|
@ -555,10 +555,10 @@ namespace spot
|
|||
if (artificial_initial_state_mode)
|
||||
{
|
||||
state_ta_explicit* artificial_init_state =
|
||||
new state_ta_explicit(tgba_init_state->clone(), bddfalse, true);
|
||||
new state_ta_explicit(tgba_init_state->clone(), bddfalse, true);
|
||||
|
||||
ta = make_ta_explicit(tgba_, tgba_->acc().num_sets(),
|
||||
artificial_init_state);
|
||||
artificial_init_state);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -568,8 +568,8 @@ namespace spot
|
|||
|
||||
// build ta automaton
|
||||
build_ta(ta, atomic_propositions_set_, degeneralized,
|
||||
single_pass_emptiness_check, artificial_livelock_state_mode,
|
||||
no_livelock);
|
||||
single_pass_emptiness_check, artificial_livelock_state_mode,
|
||||
no_livelock);
|
||||
|
||||
// (degeneralized=true) => TA
|
||||
if (degeneralized)
|
||||
|
|
@ -589,8 +589,8 @@ namespace spot
|
|||
state_ta_explicit::transitions::iterator it_trans;
|
||||
|
||||
for (it_trans = trans->begin(); it_trans != trans->end();
|
||||
++it_trans)
|
||||
(*it_trans)->acceptance_conditions = ta->acc().all_sets();
|
||||
++it_trans)
|
||||
(*it_trans)->acceptance_conditions = ta->acc().all_sets();
|
||||
|
||||
state->set_accepting_state(false);
|
||||
}
|
||||
|
|
@ -604,11 +604,11 @@ namespace spot
|
|||
{
|
||||
auto tgba_init_state = tgba_->get_init_state();
|
||||
auto artificial_init_state = new state_ta_explicit(tgba_init_state->clone(),
|
||||
bddfalse, true);
|
||||
bddfalse, true);
|
||||
tgba_init_state->destroy();
|
||||
|
||||
auto tgta = make_tgta_explicit(tgba_, tgba_->acc().num_sets(),
|
||||
artificial_init_state);
|
||||
artificial_init_state);
|
||||
|
||||
// build a Generalized TA automaton involving a single_pass_emptiness_check
|
||||
// (without an artificial livelock state):
|
||||
|
|
@ -625,14 +625,14 @@ namespace spot
|
|||
initial_states_iter->first();
|
||||
if (initial_states_iter->done())
|
||||
{
|
||||
delete initial_states_iter;
|
||||
return tgta;
|
||||
delete initial_states_iter;
|
||||
return tgta;
|
||||
}
|
||||
bdd first_state_condition = initial_states_iter->cond();
|
||||
delete initial_states_iter;
|
||||
|
||||
bdd bdd_stutering_transition = bdd_setxor(first_state_condition,
|
||||
first_state_condition);
|
||||
first_state_condition);
|
||||
|
||||
for (it = states_set.begin(); it != states_set.end(); ++it)
|
||||
{
|
||||
|
|
@ -645,13 +645,13 @@ namespace spot
|
|||
if (trans_empty || state->is_accepting_state())
|
||||
{
|
||||
ta->create_transition(state, bdd_stutering_transition,
|
||||
ta->acc().all_sets(), state);
|
||||
ta->acc().all_sets(), state);
|
||||
}
|
||||
}
|
||||
|
||||
if (state->compare(ta->get_artificial_initial_state()))
|
||||
ta->create_transition(state, bdd_stutering_transition,
|
||||
0U, state);
|
||||
0U, state);
|
||||
|
||||
state->set_livelock_accepting_state(false);
|
||||
state->set_accepting_state(false);
|
||||
|
|
|
|||
|
|
@ -83,11 +83,11 @@ namespace spot
|
|||
/// TGBA \a tgba_to_convert.
|
||||
SPOT_API ta_explicit_ptr
|
||||
tgba_to_ta(const const_twa_ptr& tgba_to_convert, bdd atomic_propositions_set,
|
||||
bool degeneralized = true,
|
||||
bool artificial_initial_state_mode = true,
|
||||
bool single_pass_emptiness_check = false,
|
||||
bool artificial_livelock_state_mode = false,
|
||||
bool no_livelock = false);
|
||||
bool degeneralized = true,
|
||||
bool artificial_initial_state_mode = true,
|
||||
bool single_pass_emptiness_check = false,
|
||||
bool artificial_livelock_state_mode = false,
|
||||
bool no_livelock = false);
|
||||
|
||||
/// \ingroup tgba_ta
|
||||
/// \brief Build a spot::tgta_explicit* (TGTA) from an LTL formula.
|
||||
|
|
@ -100,5 +100,5 @@ namespace spot
|
|||
/// language as the TGBA \a tgba_to_convert.
|
||||
SPOT_API tgta_explicit_ptr
|
||||
tgba_to_tgta(const const_twa_ptr& tgba_to_convert,
|
||||
bdd atomic_propositions_set);
|
||||
bdd atomic_propositions_set);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ namespace spot
|
|||
atomic_prop_set res;
|
||||
for (unsigned i = 0; i < n; ++i)
|
||||
{
|
||||
std::ostringstream p;
|
||||
p << 'p' << i;
|
||||
res.insert(formula::ap(p.str()));
|
||||
std::ostringstream p;
|
||||
p << 'p' << i;
|
||||
res.insert(formula::ap(p.str()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -44,11 +44,11 @@ namespace spot
|
|||
if (!s)
|
||||
s = new atomic_prop_set;
|
||||
f.traverse([&](const formula& f)
|
||||
{
|
||||
if (f.is(op::ap))
|
||||
s->insert(f);
|
||||
return false;
|
||||
});
|
||||
{
|
||||
if (f.is(op::ap))
|
||||
s->insert(f);
|
||||
return false;
|
||||
});
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ namespace spot
|
|||
// Check whether L(l) is a subset of L(g).
|
||||
bool
|
||||
language_containment_checker::contained(formula l,
|
||||
formula g)
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return true;
|
||||
|
|
@ -77,7 +77,7 @@ namespace spot
|
|||
// Check whether L(!l) is a subset of L(g).
|
||||
bool
|
||||
language_containment_checker::neg_contained(formula l,
|
||||
formula g)
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return false;
|
||||
|
|
@ -92,7 +92,7 @@ namespace spot
|
|||
// Check whether L(l) is a subset of L(!g).
|
||||
bool
|
||||
language_containment_checker::contained_neg(formula l,
|
||||
formula g)
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return false;
|
||||
|
|
@ -122,7 +122,7 @@ namespace spot
|
|||
return &i->second;
|
||||
|
||||
auto e = ltl_to_tgba_fm(f, dict_, exprop_, symb_merge_,
|
||||
branching_postponement_, fair_loop_approx_);
|
||||
branching_postponement_, fair_loop_approx_);
|
||||
record_& r = translated_[f];
|
||||
r.translation = e;
|
||||
return &r;
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ namespace spot
|
|||
/// This class uses spot::ltl_to_tgba_fm to translate LTL
|
||||
/// formulae. See that function for the meaning of these options.
|
||||
language_containment_checker(const bdd_dict_ptr& dict, bool exprop,
|
||||
bool symb_merge,
|
||||
bool branching_postponement,
|
||||
bool fair_loop_approx);
|
||||
bool symb_merge,
|
||||
bool branching_postponement,
|
||||
bool fair_loop_approx);
|
||||
|
||||
~language_containment_checker();
|
||||
|
||||
|
|
|
|||
156
spot/tl/dot.cc
156
spot/tl/dot.cc
|
|
@ -37,94 +37,94 @@ namespace spot
|
|||
std::ostringstream* sinks_;
|
||||
|
||||
dot_printer(std::ostream& os, formula f)
|
||||
: os_(os), sinks_(new std::ostringstream)
|
||||
{
|
||||
os_ << "digraph G {\n";
|
||||
rec(f);
|
||||
os_ << " subgraph atoms {\n rank=sink;\n"
|
||||
<< sinks_->str() << " }\n}\n";
|
||||
}
|
||||
: os_(os), sinks_(new std::ostringstream)
|
||||
{
|
||||
os_ << "digraph G {\n";
|
||||
rec(f);
|
||||
os_ << " subgraph atoms {\n rank=sink;\n"
|
||||
<< sinks_->str() << " }\n}\n";
|
||||
}
|
||||
|
||||
~dot_printer()
|
||||
{
|
||||
delete sinks_;
|
||||
}
|
||||
{
|
||||
delete sinks_;
|
||||
}
|
||||
|
||||
int rec(formula f)
|
||||
{
|
||||
auto i = node_.emplace(f, node_.size());
|
||||
int src = i.first->second;
|
||||
if (!i.second)
|
||||
return src;
|
||||
auto i = node_.emplace(f, node_.size());
|
||||
int src = i.first->second;
|
||||
if (!i.second)
|
||||
return src;
|
||||
|
||||
op o = f.kind();
|
||||
std::string str = (o == op::ap) ? f.ap_name() : f.kindstr();
|
||||
op o = f.kind();
|
||||
std::string str = (o == op::ap) ? f.ap_name() : f.kindstr();
|
||||
|
||||
if (o == op::ap || f.is_constant())
|
||||
*sinks_ << " " << src << " [label=\""
|
||||
<< str << "\", shape=box];\n";
|
||||
else
|
||||
os_ << " " << src << " [label=\"" << str << "\"];\n";
|
||||
if (o == op::ap || f.is_constant())
|
||||
*sinks_ << " " << src << " [label=\""
|
||||
<< str << "\", shape=box];\n";
|
||||
else
|
||||
os_ << " " << src << " [label=\"" << str << "\"];\n";
|
||||
|
||||
int childnum = 0;
|
||||
switch (o)
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
childnum = 0; // No number for children
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
childnum = -2; // L and R markers
|
||||
break;
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
childnum = 1; // Numbered children
|
||||
break;
|
||||
}
|
||||
int childnum = 0;
|
||||
switch (o)
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
childnum = 0; // No number for children
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
childnum = -2; // L and R markers
|
||||
break;
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
childnum = 1; // Numbered children
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto c: f)
|
||||
{
|
||||
// Do not merge the next two lines, as there is no
|
||||
// guarantee that rec will be called before we start
|
||||
// printing the transition.
|
||||
int dst = rec(c);
|
||||
os_ << " " << src << " -> " << dst;
|
||||
if (childnum > 0)
|
||||
os_ << " [taillabel=\"" << childnum << "\"]";
|
||||
if (childnum == -2)
|
||||
os_ << " [taillabel=\"L\"]";
|
||||
else if (childnum == -1)
|
||||
os_ << " [taillabel=\"R\"]";
|
||||
os_ << ";\n";
|
||||
++childnum;
|
||||
}
|
||||
for (auto c: f)
|
||||
{
|
||||
// Do not merge the next two lines, as there is no
|
||||
// guarantee that rec will be called before we start
|
||||
// printing the transition.
|
||||
int dst = rec(c);
|
||||
os_ << " " << src << " -> " << dst;
|
||||
if (childnum > 0)
|
||||
os_ << " [taillabel=\"" << childnum << "\"]";
|
||||
if (childnum == -2)
|
||||
os_ << " [taillabel=\"L\"]";
|
||||
else if (childnum == -1)
|
||||
os_ << " [taillabel=\"R\"]";
|
||||
os_ << ";\n";
|
||||
++childnum;
|
||||
}
|
||||
|
||||
return src;
|
||||
return src;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,66 +33,66 @@ namespace spot
|
|||
std::vector<formula> group;
|
||||
auto start = arg;
|
||||
while (*start)
|
||||
{
|
||||
while (*start == ' ' || *start == '\t')
|
||||
++start;
|
||||
if (!*start)
|
||||
break;
|
||||
if (*start == ',')
|
||||
{
|
||||
std::string s = "unexpected ',' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
if (*start == '"')
|
||||
{
|
||||
++start;
|
||||
auto end = start;
|
||||
while (*end && *end != '"')
|
||||
{
|
||||
if (*end == '\\')
|
||||
++end;
|
||||
++end;
|
||||
}
|
||||
if (!*end)
|
||||
{
|
||||
std::string s = "missing closing '\"' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
std::string ap(start, end - start);
|
||||
group.emplace_back(formula::ap(ap));
|
||||
do
|
||||
++end;
|
||||
while (*end == ' ' || *end == '\t');
|
||||
if (*end && *end != ',')
|
||||
{
|
||||
std::string s = "unexpected character '";
|
||||
s += *end;
|
||||
s += "' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
if (*end == ',')
|
||||
++end;
|
||||
start = end;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto end = start;
|
||||
while (*end && *end != ',')
|
||||
++end;
|
||||
auto rend = end;
|
||||
while (rend > start && (rend[-1] == ' ' || rend[-1] == '\t'))
|
||||
--rend;
|
||||
std::string ap(start, rend - start);
|
||||
group.emplace_back(formula::ap(ap));
|
||||
if (*end == ',')
|
||||
start = end + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
while (*start == ' ' || *start == '\t')
|
||||
++start;
|
||||
if (!*start)
|
||||
break;
|
||||
if (*start == ',')
|
||||
{
|
||||
std::string s = "unexpected ',' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
if (*start == '"')
|
||||
{
|
||||
++start;
|
||||
auto end = start;
|
||||
while (*end && *end != '"')
|
||||
{
|
||||
if (*end == '\\')
|
||||
++end;
|
||||
++end;
|
||||
}
|
||||
if (!*end)
|
||||
{
|
||||
std::string s = "missing closing '\"' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
std::string ap(start, end - start);
|
||||
group.emplace_back(formula::ap(ap));
|
||||
do
|
||||
++end;
|
||||
while (*end == ' ' || *end == '\t');
|
||||
if (*end && *end != ',')
|
||||
{
|
||||
std::string s = "unexpected character '";
|
||||
s += *end;
|
||||
s += "' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
if (*end == ',')
|
||||
++end;
|
||||
start = end;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto end = start;
|
||||
while (*end && *end != ',')
|
||||
++end;
|
||||
auto rend = end;
|
||||
while (rend > start && (rend[-1] == ' ' || rend[-1] == '\t'))
|
||||
--rend;
|
||||
std::string ap(start, rend - start);
|
||||
group.emplace_back(formula::ap(ap));
|
||||
if (*end == ',')
|
||||
start = end + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
|
@ -126,16 +126,16 @@ namespace spot
|
|||
|
||||
for (auto& g: groups)
|
||||
{
|
||||
group.clear();
|
||||
group.clear();
|
||||
|
||||
for (auto ap: g)
|
||||
if (s->find(ap) != s->end())
|
||||
group.push_back(ap);
|
||||
for (auto ap: g)
|
||||
if (s->find(ap) != s->end())
|
||||
group.push_back(ap);
|
||||
|
||||
unsigned s = group.size();
|
||||
for (unsigned j = 0; j < s; ++j)
|
||||
for (unsigned k = j + 1; k < s; ++k)
|
||||
v.push_back(nand(group[j], group[k]));
|
||||
unsigned s = group.size();
|
||||
for (unsigned j = 0; j < s; ++j)
|
||||
for (unsigned k = j + 1; k < s; ++k)
|
||||
v.push_back(nand(group[j], group[k]));
|
||||
};
|
||||
|
||||
delete s;
|
||||
|
|
@ -143,15 +143,15 @@ namespace spot
|
|||
}
|
||||
|
||||
twa_graph_ptr exclusive_ap::constrain(const_twa_graph_ptr aut,
|
||||
bool simplify_guards) const
|
||||
bool simplify_guards) const
|
||||
{
|
||||
// Compute the support of the automaton.
|
||||
bdd support = bddtrue;
|
||||
{
|
||||
std::set<int> bdd_seen;
|
||||
for (auto& t: aut->edges())
|
||||
if (bdd_seen.insert(t.cond.id()).second)
|
||||
support &= bdd_support(t.cond);
|
||||
if (bdd_seen.insert(t.cond.id()).second)
|
||||
support &= bdd_support(t.cond);
|
||||
}
|
||||
|
||||
bdd restrict = bddtrue;
|
||||
|
|
@ -160,19 +160,19 @@ namespace spot
|
|||
std::vector<bdd> group;
|
||||
for (auto& g: groups)
|
||||
{
|
||||
group.clear();
|
||||
group.clear();
|
||||
|
||||
for (auto ap: g)
|
||||
{
|
||||
int v = d->has_registered_proposition(ap, aut);
|
||||
if (v >= 0)
|
||||
group.push_back(bdd_nithvar(v));
|
||||
}
|
||||
for (auto ap: g)
|
||||
{
|
||||
int v = d->has_registered_proposition(ap, aut);
|
||||
if (v >= 0)
|
||||
group.push_back(bdd_nithvar(v));
|
||||
}
|
||||
|
||||
unsigned s = group.size();
|
||||
for (unsigned j = 0; j < s; ++j)
|
||||
for (unsigned k = j + 1; k < s; ++k)
|
||||
restrict &= group[j] | group[k];
|
||||
unsigned s = group.size();
|
||||
for (unsigned j = 0; j < s; ++j)
|
||||
for (unsigned k = j + 1; k < s; ++k)
|
||||
restrict &= group[j] | group[k];
|
||||
}
|
||||
|
||||
twa_graph_ptr res = make_twa_graph(aut->get_dict());
|
||||
|
|
@ -181,26 +181,26 @@ namespace spot
|
|||
res->copy_acceptance_of(aut);
|
||||
if (simplify_guards)
|
||||
{
|
||||
transform_accessible(aut, res, [&](unsigned, bdd& cond,
|
||||
acc_cond::mark_t&, unsigned)
|
||||
{
|
||||
minato_isop isop(cond & restrict,
|
||||
cond | !restrict,
|
||||
true);
|
||||
bdd res = bddfalse;
|
||||
bdd cube = bddfalse;
|
||||
while ((cube = isop.next()) != bddfalse)
|
||||
res |= cube;
|
||||
cond = res;
|
||||
});
|
||||
transform_accessible(aut, res, [&](unsigned, bdd& cond,
|
||||
acc_cond::mark_t&, unsigned)
|
||||
{
|
||||
minato_isop isop(cond & restrict,
|
||||
cond | !restrict,
|
||||
true);
|
||||
bdd res = bddfalse;
|
||||
bdd cube = bddfalse;
|
||||
while ((cube = isop.next()) != bddfalse)
|
||||
res |= cube;
|
||||
cond = res;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
transform_accessible(aut, res, [&](unsigned, bdd& cond,
|
||||
acc_cond::mark_t&, unsigned)
|
||||
{
|
||||
cond &= restrict;
|
||||
});
|
||||
transform_accessible(aut, res, [&](unsigned, bdd& cond,
|
||||
acc_cond::mark_t&, unsigned)
|
||||
{
|
||||
cond &= restrict;
|
||||
});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,6 @@ namespace spot
|
|||
|
||||
formula constrain(formula f) const;
|
||||
twa_graph_ptr constrain(const_twa_graph_ptr aut,
|
||||
bool simplify_guards = false) const;
|
||||
bool simplify_guards = false) const;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
2524
spot/tl/formula.cc
2524
spot/tl/formula.cc
File diff suppressed because it is too large
Load diff
1292
spot/tl/formula.hh
1292
spot/tl/formula.hh
File diff suppressed because it is too large
Load diff
|
|
@ -30,14 +30,14 @@ namespace spot
|
|||
{
|
||||
int len = 0;
|
||||
f.traverse([&len](const formula& x)
|
||||
{
|
||||
auto s = x.size();
|
||||
if (s > 1)
|
||||
len += s - 1;
|
||||
else
|
||||
++len;
|
||||
return false;
|
||||
});
|
||||
{
|
||||
auto s = x.size();
|
||||
if (s > 1)
|
||||
len += s - 1;
|
||||
else
|
||||
++len;
|
||||
return false;
|
||||
});
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
@ -46,31 +46,31 @@ namespace spot
|
|||
{
|
||||
int len = 0;
|
||||
f.traverse([&len](const formula& x)
|
||||
{
|
||||
if (x.is_boolean())
|
||||
{
|
||||
++len;
|
||||
return true;
|
||||
}
|
||||
auto s = x.size();
|
||||
if (s > 2)
|
||||
{
|
||||
int b = 0;
|
||||
for (const auto& y: x)
|
||||
if (y.is_boolean())
|
||||
++b;
|
||||
len += s - b * 2 + 1;
|
||||
}
|
||||
else if (s > 1)
|
||||
{
|
||||
len += s - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++len;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
{
|
||||
if (x.is_boolean())
|
||||
{
|
||||
++len;
|
||||
return true;
|
||||
}
|
||||
auto s = x.size();
|
||||
if (s > 2)
|
||||
{
|
||||
int b = 0;
|
||||
for (const auto& y: x)
|
||||
if (y.is_boolean())
|
||||
++b;
|
||||
len += s - b * 2 + 1;
|
||||
}
|
||||
else if (s > 1)
|
||||
{
|
||||
len += s - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++len;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
|
|||
126
spot/tl/mark.cc
126
spot/tl/mark.cc
|
|
@ -58,25 +58,25 @@ namespace spot
|
|||
case op::UConcat:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
res = f;
|
||||
break;
|
||||
res = f;
|
||||
break;
|
||||
case op::NegClosure:
|
||||
res = formula::NegClosureMarked(f[0]);
|
||||
break;
|
||||
res = formula::NegClosureMarked(f[0]);
|
||||
break;
|
||||
case op::EConcat:
|
||||
res = formula::EConcatMarked(f[0], f[1]);
|
||||
break;
|
||||
res = formula::EConcatMarked(f[0], f[1]);
|
||||
break;
|
||||
case op::Or:
|
||||
case op::And:
|
||||
res = f.map([this](formula f)
|
||||
{
|
||||
return this->mark_concat_ops(f);
|
||||
});
|
||||
break;
|
||||
res = f.map([this](formula f)
|
||||
{
|
||||
return this->mark_concat_ops(f);
|
||||
});
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
SPOT_UNIMPLEMENTED();
|
||||
SPOT_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
markops_[f] = res;
|
||||
|
|
@ -95,7 +95,7 @@ namespace spot
|
|||
|
||||
auto recurse = [this](formula f)
|
||||
{
|
||||
return this->simplify_mark(f);
|
||||
return this->simplify_mark(f);
|
||||
};
|
||||
|
||||
formula res;
|
||||
|
|
@ -119,58 +119,58 @@ namespace spot
|
|||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
res = f;
|
||||
break;
|
||||
res = f;
|
||||
break;
|
||||
case op::Or:
|
||||
res = f.map(recurse);
|
||||
break;
|
||||
res = f.map(recurse);
|
||||
break;
|
||||
case op::And:
|
||||
{
|
||||
std::set<std::pair<formula, formula>> empairs;
|
||||
std::set<formula> nmset;
|
||||
std::vector<formula> elist;
|
||||
std::vector<formula> nlist;
|
||||
std::vector<formula> v;
|
||||
{
|
||||
std::set<std::pair<formula, formula>> empairs;
|
||||
std::set<formula> nmset;
|
||||
std::vector<formula> elist;
|
||||
std::vector<formula> nlist;
|
||||
std::vector<formula> v;
|
||||
|
||||
for (auto c: f)
|
||||
{
|
||||
if (c.is(op::EConcatMarked))
|
||||
{
|
||||
empairs.emplace(c[0], c[1]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::EConcat))
|
||||
{
|
||||
elist.push_back(c);
|
||||
}
|
||||
else if (c.is(op::NegClosureMarked))
|
||||
{
|
||||
nmset.insert(c[0]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::NegClosure))
|
||||
{
|
||||
nlist.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.push_back(c);
|
||||
}
|
||||
}
|
||||
// Keep only the non-marked EConcat for which we
|
||||
// have not seen a similar EConcatMarked.
|
||||
for (auto e: elist)
|
||||
if (empairs.find(std::make_pair(e[0], e[1]))
|
||||
== empairs.end())
|
||||
v.push_back(e);
|
||||
// Keep only the non-marked NegClosure for which we
|
||||
// have not seen a similar NegClosureMarked.
|
||||
for (auto n: nlist)
|
||||
if (nmset.find(n[0]) == nmset.end())
|
||||
v.push_back(n);
|
||||
res = formula::And(v);
|
||||
}
|
||||
break;
|
||||
for (auto c: f)
|
||||
{
|
||||
if (c.is(op::EConcatMarked))
|
||||
{
|
||||
empairs.emplace(c[0], c[1]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::EConcat))
|
||||
{
|
||||
elist.push_back(c);
|
||||
}
|
||||
else if (c.is(op::NegClosureMarked))
|
||||
{
|
||||
nmset.insert(c[0]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::NegClosure))
|
||||
{
|
||||
nlist.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.push_back(c);
|
||||
}
|
||||
}
|
||||
// Keep only the non-marked EConcat for which we
|
||||
// have not seen a similar EConcatMarked.
|
||||
for (auto e: elist)
|
||||
if (empairs.find(std::make_pair(e[0], e[1]))
|
||||
== empairs.end())
|
||||
v.push_back(e);
|
||||
// Keep only the non-marked NegClosure for which we
|
||||
// have not seen a similar NegClosureMarked.
|
||||
for (auto n: nlist)
|
||||
if (nmset.find(n[0]) == nmset.end())
|
||||
v.push_back(n);
|
||||
res = formula::And(v);
|
||||
}
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
|
|
@ -181,7 +181,7 @@ namespace spot
|
|||
case op::FStar:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
SPOT_UNIMPLEMENTED();
|
||||
SPOT_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
simpmark_[f] = res;
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ namespace spot
|
|||
formula substitute_ap(formula f, formula ap_src, formula ap_dst)
|
||||
{
|
||||
return f.map([&](formula f)
|
||||
{
|
||||
if (f == ap_src)
|
||||
return ap_dst;
|
||||
else
|
||||
return substitute_ap(f, ap_src, ap_dst);
|
||||
});
|
||||
{
|
||||
if (f == ap_src)
|
||||
return ap_dst;
|
||||
else
|
||||
return substitute_ap(f, ap_src, ap_dst);
|
||||
});
|
||||
}
|
||||
|
||||
typedef std::vector<formula> vec;
|
||||
|
|
@ -58,229 +58,229 @@ namespace spot
|
|||
|
||||
formula mutate(formula f)
|
||||
{
|
||||
auto recurse = [this](formula f)
|
||||
{
|
||||
return this->mutate(f);
|
||||
};
|
||||
auto recurse = [this](formula f)
|
||||
{
|
||||
return this->mutate(f);
|
||||
};
|
||||
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
return f;
|
||||
case op::ap:
|
||||
if (opts_ & Mut_Ap2Const)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::tt();
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::ff();
|
||||
}
|
||||
return f;
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
if ((opts_ & Mut_Remove_Ops)
|
||||
&& mutation_counter_-- == 0)
|
||||
return f[0];
|
||||
// fall through
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
{
|
||||
int mos = f.size();
|
||||
if (opts_ & Mut_Remove_Multop_Operands)
|
||||
{
|
||||
for (int i = 0; i < mos; ++i)
|
||||
if (mutation_counter_-- == 0)
|
||||
return f.all_but(i);
|
||||
}
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
return f;
|
||||
case op::ap:
|
||||
if (opts_ & Mut_Ap2Const)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::tt();
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::ff();
|
||||
}
|
||||
return f;
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
if ((opts_ & Mut_Remove_Ops)
|
||||
&& mutation_counter_-- == 0)
|
||||
return f[0];
|
||||
// fall through
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
{
|
||||
int mos = f.size();
|
||||
if (opts_ & Mut_Remove_Multop_Operands)
|
||||
{
|
||||
for (int i = 0; i < mos; ++i)
|
||||
if (mutation_counter_-- == 0)
|
||||
return f.all_but(i);
|
||||
}
|
||||
|
||||
if (opts_ & Mut_Split_Ops && f.is(op::AndNLM))
|
||||
{
|
||||
if (mutation_counter_ >= 0
|
||||
&& mutation_counter_ < 2 * (mos - 1))
|
||||
{
|
||||
vec v1;
|
||||
vec v2;
|
||||
v1.push_back(f[0]);
|
||||
bool reverse = false;
|
||||
int i = 1;
|
||||
while (i < mos)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
break;
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
reverse = true;
|
||||
break;
|
||||
}
|
||||
v1.push_back(f[i++]);
|
||||
}
|
||||
for (; i < mos; ++i)
|
||||
v2.push_back(f[i]);
|
||||
formula first = AndNLM_(v1);
|
||||
formula second = AndNLM_(v2);
|
||||
formula ost = formula::one_star();
|
||||
if (!reverse)
|
||||
return AndRat_(Concat_(first, ost), second);
|
||||
else
|
||||
return AndRat_(Concat_(second, ost), first);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutation_counter_ -= 2 * (mos - 1);
|
||||
}
|
||||
}
|
||||
if (opts_ & Mut_Split_Ops && f.is(op::AndNLM))
|
||||
{
|
||||
if (mutation_counter_ >= 0
|
||||
&& mutation_counter_ < 2 * (mos - 1))
|
||||
{
|
||||
vec v1;
|
||||
vec v2;
|
||||
v1.push_back(f[0]);
|
||||
bool reverse = false;
|
||||
int i = 1;
|
||||
while (i < mos)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
break;
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
reverse = true;
|
||||
break;
|
||||
}
|
||||
v1.push_back(f[i++]);
|
||||
}
|
||||
for (; i < mos; ++i)
|
||||
v2.push_back(f[i]);
|
||||
formula first = AndNLM_(v1);
|
||||
formula second = AndNLM_(v2);
|
||||
formula ost = formula::one_star();
|
||||
if (!reverse)
|
||||
return AndRat_(Concat_(first, ost), second);
|
||||
else
|
||||
return AndRat_(Concat_(second, ost), first);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutation_counter_ -= 2 * (mos - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
{
|
||||
formula first = f[0];
|
||||
formula second = f[1];
|
||||
op o = f.kind();
|
||||
bool left_is_sere = o == op::EConcat
|
||||
|| o == op::EConcatMarked
|
||||
|| o == op::UConcat;
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
{
|
||||
formula first = f[0];
|
||||
formula second = f[1];
|
||||
op o = f.kind();
|
||||
bool left_is_sere = o == op::EConcat
|
||||
|| o == op::EConcatMarked
|
||||
|| o == op::UConcat;
|
||||
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
{
|
||||
if (!left_is_sere)
|
||||
return first;
|
||||
else if (o == op::UConcat)
|
||||
return formula::NegClosure(first);
|
||||
else // EConcat or EConcatMarked
|
||||
return formula::Closure(first);
|
||||
}
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return second;
|
||||
if (opts_ & Mut_Rewrite_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::U:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(first, second);
|
||||
break;
|
||||
case op::M:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::R(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::U(second, first);
|
||||
break;
|
||||
case op::R:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(second, first);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opts_ & Mut_Split_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::Equiv:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(second, first);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, second});
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
// Negate the two argument sequentially (in this
|
||||
// case right before left, otherwise different
|
||||
// compilers will make different choices.
|
||||
auto right = formula::Not(second);
|
||||
return formula::And({formula::Not(first), right});
|
||||
}
|
||||
break;
|
||||
case op::Xor:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, formula::Not(second)});
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({formula::Not(first), second});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
{
|
||||
formula c = f[0];
|
||||
op o = f.kind();
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return c;
|
||||
if (opts_ & Mut_Simplify_Bounds)
|
||||
{
|
||||
auto min = f.min();
|
||||
auto max = f.max();
|
||||
if (min > 0)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min - 1, max);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, 0, max);
|
||||
}
|
||||
if (max != formula::unbounded())
|
||||
{
|
||||
if (max > min && mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min, max - 1);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min,
|
||||
formula::unbounded());
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
{
|
||||
if (!left_is_sere)
|
||||
return first;
|
||||
else if (o == op::UConcat)
|
||||
return formula::NegClosure(first);
|
||||
else // EConcat or EConcatMarked
|
||||
return formula::Closure(first);
|
||||
}
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return second;
|
||||
if (opts_ & Mut_Rewrite_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::U:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(first, second);
|
||||
break;
|
||||
case op::M:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::R(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::U(second, first);
|
||||
break;
|
||||
case op::R:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(second, first);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opts_ & Mut_Split_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::Equiv:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(second, first);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, second});
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
// Negate the two argument sequentially (in this
|
||||
// case right before left, otherwise different
|
||||
// compilers will make different choices.
|
||||
auto right = formula::Not(second);
|
||||
return formula::And({formula::Not(first), right});
|
||||
}
|
||||
break;
|
||||
case op::Xor:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, formula::Not(second)});
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({formula::Not(first), second});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
{
|
||||
formula c = f[0];
|
||||
op o = f.kind();
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return c;
|
||||
if (opts_ & Mut_Simplify_Bounds)
|
||||
{
|
||||
auto min = f.min();
|
||||
auto max = f.max();
|
||||
if (min > 0)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min - 1, max);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, 0, max);
|
||||
}
|
||||
if (max != formula::unbounded())
|
||||
{
|
||||
if (max > min && mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min, max - 1);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min,
|
||||
formula::unbounded());
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
|
||||
formula
|
||||
get_mutation(int n)
|
||||
{
|
||||
mutation_counter_ = n;
|
||||
formula mut = mutate(f_);
|
||||
if (mut == f_)
|
||||
return nullptr;
|
||||
return mut;
|
||||
mutation_counter_ = n;
|
||||
formula mut = mutate(f_);
|
||||
if (mut == f_)
|
||||
return nullptr;
|
||||
return mut;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -291,13 +291,13 @@ namespace spot
|
|||
assert(left != nullptr);
|
||||
assert(right != nullptr);
|
||||
if (left == right)
|
||||
return false;
|
||||
return false;
|
||||
auto ll = length(left);
|
||||
auto lr = length(right);
|
||||
if (ll < lr)
|
||||
return true;
|
||||
return true;
|
||||
if (ll > lr)
|
||||
return false;
|
||||
return false;
|
||||
return left < right;
|
||||
}
|
||||
|
||||
|
|
@ -305,55 +305,55 @@ namespace spot
|
|||
|
||||
void
|
||||
single_mutation_rec(formula f, fset_t& mutations, unsigned opts,
|
||||
unsigned& n, unsigned m)
|
||||
unsigned& n, unsigned m)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula mut;
|
||||
int i = 0;
|
||||
mutator mv(f, opts);
|
||||
while (n > 0 && ((mut = mv.get_mutation(i++)) != nullptr))
|
||||
single_mutation_rec(mut, mutations, opts, n, m - 1);
|
||||
}
|
||||
{
|
||||
formula mut;
|
||||
int i = 0;
|
||||
mutator mv(f, opts);
|
||||
while (n > 0 && ((mut = mv.get_mutation(i++)) != nullptr))
|
||||
single_mutation_rec(mut, mutations, opts, n, m - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
replace_ap_rec(formula f, fset_t& mutations, unsigned opts,
|
||||
unsigned& n, unsigned m)
|
||||
unsigned& n, unsigned m)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!n)
|
||||
return;
|
||||
auto aps =
|
||||
std::unique_ptr<atomic_prop_set>(atomic_prop_collect(f));
|
||||
for (auto ap1: *aps)
|
||||
for (auto ap2: *aps)
|
||||
{
|
||||
if (ap1 == ap2)
|
||||
continue;
|
||||
auto mut = substitute_ap(f, ap1, ap2);
|
||||
replace_ap_rec(mut, mutations, opts, n, m - 1);
|
||||
if (!n)
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (!n)
|
||||
return;
|
||||
auto aps =
|
||||
std::unique_ptr<atomic_prop_set>(atomic_prop_collect(f));
|
||||
for (auto ap1: *aps)
|
||||
for (auto ap2: *aps)
|
||||
{
|
||||
if (ap1 == ap2)
|
||||
continue;
|
||||
auto mut = substitute_ap(f, ap1, ap2);
|
||||
replace_ap_rec(mut, mutations, opts, n, m - 1);
|
||||
if (!n)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<formula>
|
||||
mutate(formula f, unsigned opts, unsigned max_output,
|
||||
unsigned mutation_count, bool sort)
|
||||
unsigned mutation_count, bool sort)
|
||||
{
|
||||
fset_t mutations;
|
||||
single_mutation_rec(f, mutations, opts, max_output, mutation_count);
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ namespace spot
|
|||
|
||||
SPOT_API
|
||||
std::vector<formula> mutate(formula f,
|
||||
unsigned opts = Mut_All,
|
||||
unsigned max_output = -1U,
|
||||
unsigned mutation_count = 1,
|
||||
bool sort = true);
|
||||
unsigned opts = Mut_All,
|
||||
unsigned max_output = -1U,
|
||||
unsigned mutation_count = 1,
|
||||
bool sort = true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,8 +94,8 @@ namespace spot
|
|||
/// \param shift how many characters to add to the error locations
|
||||
/// \return \c true iff any diagnostic was output.
|
||||
bool format_errors(std::ostream& os,
|
||||
const std::string& input,
|
||||
unsigned shift);
|
||||
const std::string& input,
|
||||
unsigned shift);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -119,10 +119,10 @@ namespace spot
|
|||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
parsed_formula parse_infix_psl(const std::string& ltl_string,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
|
||||
/// \brief Build a Boolean formula from a string.
|
||||
/// \param ltl_string The string to parse.
|
||||
|
|
@ -142,10 +142,10 @@ namespace spot
|
|||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
parsed_formula parse_infix_boolean(const std::string& ltl_string,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
|
||||
/// \brief Build a formula from an LTL string in LBT's format.
|
||||
/// \param ltl_string The string to parse.
|
||||
|
|
@ -167,9 +167,9 @@ namespace spot
|
|||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
parsed_formula parse_prefix_ltl(const std::string& ltl_string,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false);
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false);
|
||||
|
||||
/// \brief A simple wrapper to parse_infix_psl() and parse_prefix_ltl().
|
||||
///
|
||||
|
|
@ -179,7 +179,7 @@ namespace spot
|
|||
/// parse_infix_psl() as a parse_error exception.
|
||||
SPOT_API formula
|
||||
parse_formula(const std::string& ltl_string,
|
||||
environment& env = default_environment::instance());
|
||||
environment& env = default_environment::instance());
|
||||
|
||||
/// \brief Build a formula from a string representing a SERE.
|
||||
/// \param sere_string The string to parse.
|
||||
|
|
@ -200,10 +200,10 @@ namespace spot
|
|||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
parsed_formula parse_infix_sere(const std::string& sere_string,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
|
||||
/// \brief Fix location of diagnostics assuming the input is utf8.
|
||||
///
|
||||
|
|
@ -230,7 +230,7 @@ namespace spot
|
|||
SPOT_API
|
||||
void
|
||||
fix_utf8_locations(const std::string& input_string,
|
||||
parse_error_list& error_list);
|
||||
parse_error_list& error_list);
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
1218
spot/tl/print.cc
1218
spot/tl/print.cc
File diff suppressed because it is too large
Load diff
|
|
@ -34,14 +34,14 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_psl(std::ostream& os, formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Convert a PSL formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_psl(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -49,15 +49,15 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_utf8_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert a PSL formula into a utf-8 string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_utf8_psl(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -65,14 +65,14 @@ namespace spot
|
|||
/// \param f The formula to translate.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sere(std::ostream& os, formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Convert a SERE formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sere(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -80,15 +80,15 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_utf8_sere(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert a SERE formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_utf8_sere(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -96,15 +96,15 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_spin_ltl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert an LTL formula into a string parsable by Spin.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_spin_ltl(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -123,16 +123,16 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_latex_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a formula as a LaTeX string which is parsable.
|
||||
/// unless the formula contains automaton operators (used in ELTL formulae).
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_latex_psl(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -140,16 +140,16 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_latex_sere(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a LaTeX string which is parsable.
|
||||
/// unless the formula contains automaton operators (used in ELTL formulae).
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_latex_sere(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -159,17 +159,17 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sclatex_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a PSL formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed bacl.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sclatex_psl(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -179,17 +179,17 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sclatex_sere(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed bacl.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sclatex_sere(formula f, bool full_parent = false);
|
||||
|
||||
|
|
|
|||
|
|
@ -183,24 +183,24 @@ namespace spot
|
|||
total_2_and_more_ = 0.0;
|
||||
for (unsigned i = 0; i < proba_size_; ++i)
|
||||
{
|
||||
if (proba_[i].min_n == 1)
|
||||
{
|
||||
total_1_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_)
|
||||
total_2_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_or_more_)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
}
|
||||
else if (proba_[i].min_n == 2)
|
||||
{
|
||||
total_2_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_or_more_)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
}
|
||||
else if (proba_[i].min_n > 2)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
else
|
||||
SPOT_UNREACHABLE(); // unexpected max_n
|
||||
if (proba_[i].min_n == 1)
|
||||
{
|
||||
total_1_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_)
|
||||
total_2_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_or_more_)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
}
|
||||
else if (proba_[i].min_n == 2)
|
||||
{
|
||||
total_2_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_or_more_)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
}
|
||||
else if (proba_[i].min_n > 2)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
else
|
||||
SPOT_UNREACHABLE(); // unexpected max_n
|
||||
}
|
||||
assert(total_2_and_more_ >= total_2_);
|
||||
}
|
||||
|
|
@ -216,48 +216,48 @@ namespace spot
|
|||
// Approximate impossible cases.
|
||||
if (n == 1 && total_1_ == 0.0)
|
||||
{
|
||||
if (total_2_ != 0.0)
|
||||
n = 2;
|
||||
else
|
||||
n = 3;
|
||||
if (total_2_ != 0.0)
|
||||
n = 2;
|
||||
else
|
||||
n = 3;
|
||||
}
|
||||
else if (n == 2 && total_2_ == 0.0)
|
||||
{
|
||||
if (total_1_ != 0.0)
|
||||
n = 1;
|
||||
else
|
||||
n = 3;
|
||||
if (total_1_ != 0.0)
|
||||
n = 1;
|
||||
else
|
||||
n = 3;
|
||||
}
|
||||
else if (n > 2 && total_2_and_more_ == 0.0)
|
||||
{
|
||||
if (total_1_ != 0.0)
|
||||
n = 1;
|
||||
else
|
||||
assert(total_2_ == 0.0);
|
||||
if (total_1_ != 0.0)
|
||||
n = 1;
|
||||
else
|
||||
assert(total_2_ == 0.0);
|
||||
}
|
||||
|
||||
|
||||
if (n == 1)
|
||||
{
|
||||
r *= total_1_;
|
||||
p = proba_;
|
||||
r *= total_1_;
|
||||
p = proba_;
|
||||
}
|
||||
else if (n == 2)
|
||||
{
|
||||
r *= total_2_;
|
||||
p = proba_2_;
|
||||
r *= total_2_;
|
||||
p = proba_2_;
|
||||
}
|
||||
else
|
||||
{
|
||||
r *= total_2_and_more_;
|
||||
p = proba_2_or_more_;
|
||||
r *= total_2_and_more_;
|
||||
p = proba_2_or_more_;
|
||||
}
|
||||
|
||||
double s = p->proba;
|
||||
while (s < r)
|
||||
{
|
||||
++p;
|
||||
s += p->proba;
|
||||
++p;
|
||||
s += p->proba;
|
||||
}
|
||||
|
||||
return p->build(this, n);
|
||||
|
|
@ -271,30 +271,30 @@ namespace spot
|
|||
char* key = strtok(options, "=\t, :;");
|
||||
while (key)
|
||||
{
|
||||
char* value = strtok(nullptr, "=\t, :;");
|
||||
if (!value)
|
||||
return key;
|
||||
char* value = strtok(nullptr, "=\t, :;");
|
||||
if (!value)
|
||||
return key;
|
||||
|
||||
char* endptr;
|
||||
double res = strtod(value, &endptr);
|
||||
if (*endptr)
|
||||
return value;
|
||||
char* endptr;
|
||||
double res = strtod(value, &endptr);
|
||||
if (*endptr)
|
||||
return value;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < proba_size_; ++i)
|
||||
{
|
||||
if (('a' <= *proba_[i].name && *proba_[i].name <= 'z'
|
||||
&& !strcasecmp(proba_[i].name, key))
|
||||
|| !strcmp(proba_[i].name, key))
|
||||
{
|
||||
proba_[i].proba = res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == proba_size_)
|
||||
return key;
|
||||
unsigned i;
|
||||
for (i = 0; i < proba_size_; ++i)
|
||||
{
|
||||
if (('a' <= *proba_[i].name && *proba_[i].name <= 'z'
|
||||
&& !strcasecmp(proba_[i].name, key))
|
||||
|| !strcmp(proba_[i].name, key))
|
||||
{
|
||||
proba_[i].proba = res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == proba_size_)
|
||||
return key;
|
||||
|
||||
key = strtok(nullptr, "=\t, :;");
|
||||
key = strtok(nullptr, "=\t, :;");
|
||||
}
|
||||
update_sums();
|
||||
return nullptr;
|
||||
|
|
@ -393,7 +393,7 @@ namespace spot
|
|||
{
|
||||
// FIXME: This looks very fragile.
|
||||
memmove(proba_ + 8, proba_ + 7,
|
||||
((proba_ + 16) - (proba_ + 7)) * sizeof(*proba_));
|
||||
((proba_ + 16) - (proba_ + 7)) * sizeof(*proba_));
|
||||
|
||||
proba_[7].setup("Closure", 2, closure_builder);
|
||||
proba_[17].setup("EConcat", 3, binop_SERELTL_builder<op::EConcat>);
|
||||
|
|
@ -402,10 +402,10 @@ namespace spot
|
|||
}
|
||||
|
||||
randltlgenerator::randltlgenerator(atomic_prop_set aprops,
|
||||
const option_map& opts,
|
||||
char* opt_pL,
|
||||
char* opt_pS,
|
||||
char* opt_pB)
|
||||
const option_map& opts,
|
||||
char* opt_pL,
|
||||
char* opt_pS,
|
||||
char* opt_pB)
|
||||
{
|
||||
aprops_ = aprops;
|
||||
output_ = opts.get("output", OUTPUTLTL);
|
||||
|
|
@ -423,51 +423,51 @@ namespace spot
|
|||
switch (output_)
|
||||
{
|
||||
case OUTPUTLTL:
|
||||
rf_ = new random_ltl(&aprops_);
|
||||
if (opt_pS)
|
||||
throw std::invalid_argument("Cannot set sere priorities with "
|
||||
"LTL output");
|
||||
if (opt_pB)
|
||||
throw std::invalid_argument("Cannot set boolean priorities with "
|
||||
"LTL output");
|
||||
tok_pL = rf_->parse_options(opt_pL);
|
||||
break;
|
||||
rf_ = new random_ltl(&aprops_);
|
||||
if (opt_pS)
|
||||
throw std::invalid_argument("Cannot set sere priorities with "
|
||||
"LTL output");
|
||||
if (opt_pB)
|
||||
throw std::invalid_argument("Cannot set boolean priorities with "
|
||||
"LTL output");
|
||||
tok_pL = rf_->parse_options(opt_pL);
|
||||
break;
|
||||
case OUTPUTBOOL:
|
||||
rf_ = new random_boolean(&aprops_);
|
||||
tok_pB = rf_->parse_options(opt_pB);
|
||||
if (opt_pL)
|
||||
throw std::invalid_argument("Cannot set ltl priorities with "
|
||||
"Boolean output");
|
||||
if (opt_pS)
|
||||
throw std::invalid_argument("Cannot set sere priorities "
|
||||
"with Boolean output");
|
||||
break;
|
||||
rf_ = new random_boolean(&aprops_);
|
||||
tok_pB = rf_->parse_options(opt_pB);
|
||||
if (opt_pL)
|
||||
throw std::invalid_argument("Cannot set ltl priorities with "
|
||||
"Boolean output");
|
||||
if (opt_pS)
|
||||
throw std::invalid_argument("Cannot set sere priorities "
|
||||
"with Boolean output");
|
||||
break;
|
||||
case OUTPUTSERE:
|
||||
rf_ = rs_ = new random_sere(&aprops_);
|
||||
tok_pS = rs_->parse_options(opt_pS);
|
||||
tok_pB = rs_->rb.parse_options(opt_pB);
|
||||
if (opt_pL)
|
||||
throw std::invalid_argument("Cannot set ltl priorities "
|
||||
"with SERE output");
|
||||
break;
|
||||
rf_ = rs_ = new random_sere(&aprops_);
|
||||
tok_pS = rs_->parse_options(opt_pS);
|
||||
tok_pB = rs_->rb.parse_options(opt_pB);
|
||||
if (opt_pL)
|
||||
throw std::invalid_argument("Cannot set ltl priorities "
|
||||
"with SERE output");
|
||||
break;
|
||||
case OUTPUTPSL:
|
||||
rf_ = rp_ = new random_psl(&aprops_);
|
||||
rs_ = &rp_->rs;
|
||||
tok_pL = rp_->parse_options(opt_pL);
|
||||
tok_pS = rs_->parse_options(opt_pS);
|
||||
tok_pB = rs_->rb.parse_options(opt_pB);
|
||||
break;
|
||||
rf_ = rp_ = new random_psl(&aprops_);
|
||||
rs_ = &rp_->rs;
|
||||
tok_pL = rp_->parse_options(opt_pL);
|
||||
tok_pS = rs_->parse_options(opt_pS);
|
||||
tok_pB = rs_->rb.parse_options(opt_pB);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tok_pL)
|
||||
throw std::invalid_argument("failed to parse LTL priorities near "
|
||||
+ std::string(tok_pL));
|
||||
+ std::string(tok_pL));
|
||||
if (tok_pS)
|
||||
throw std::invalid_argument("failed to parse SERE priorities near "
|
||||
+ std::string(tok_pS));
|
||||
+ std::string(tok_pS));
|
||||
if (tok_pB)
|
||||
throw std::invalid_argument("failed to parse Boolean priorities near "
|
||||
+ std::string(tok_pB));
|
||||
+ std::string(tok_pB));
|
||||
|
||||
spot::srand(opt_seed_);
|
||||
tl_simplifier_options simpl_opts(opt_simpl_level_);
|
||||
|
|
@ -475,12 +475,12 @@ namespace spot
|
|||
}
|
||||
|
||||
randltlgenerator::randltlgenerator(int aprops_n,
|
||||
const option_map& opts,
|
||||
char* opt_pL,
|
||||
char* opt_pS,
|
||||
char* opt_pB)
|
||||
const option_map& opts,
|
||||
char* opt_pL,
|
||||
char* opt_pS,
|
||||
char* opt_pB)
|
||||
: randltlgenerator(create_atomic_prop_set(aprops_n), opts,
|
||||
opt_pL, opt_pS, opt_pB)
|
||||
opt_pL, opt_pS, opt_pB)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -496,24 +496,24 @@ namespace spot
|
|||
formula f = nullptr;
|
||||
do
|
||||
{
|
||||
ignore = false;
|
||||
int size = opt_tree_size_min_;
|
||||
if (size != opt_tree_size_max_)
|
||||
size = spot::rrand(size, opt_tree_size_max_);
|
||||
f = rf_->generate(size);
|
||||
ignore = false;
|
||||
int size = opt_tree_size_min_;
|
||||
if (size != opt_tree_size_max_)
|
||||
size = spot::rrand(size, opt_tree_size_max_);
|
||||
f = rf_->generate(size);
|
||||
|
||||
if (opt_wf_)
|
||||
{
|
||||
atomic_prop_set s = aprops_;
|
||||
remove_some_props(s);
|
||||
f = formula::And({f, GF_n()});
|
||||
}
|
||||
if (opt_wf_)
|
||||
{
|
||||
atomic_prop_set s = aprops_;
|
||||
remove_some_props(s);
|
||||
f = formula::And({f, GF_n()});
|
||||
}
|
||||
|
||||
if (opt_simpl_level_)
|
||||
f = simpl_.simplify(f);
|
||||
if (opt_simpl_level_)
|
||||
f = simpl_.simplify(f);
|
||||
|
||||
if (opt_unique_ && !unique_set_.insert(f).second)
|
||||
ignore = true;
|
||||
if (opt_unique_ && !unique_set_.insert(f).second)
|
||||
ignore = true;
|
||||
} while (ignore && --trials);
|
||||
if (trials <= 0)
|
||||
return nullptr;
|
||||
|
|
@ -529,9 +529,9 @@ namespace spot
|
|||
|
||||
while (n--)
|
||||
{
|
||||
auto i = s.begin();
|
||||
std::advance(i, spot::mrand(s.size()));
|
||||
s.erase(i);
|
||||
auto i = s.begin();
|
||||
std::advance(i, spot::mrand(s.size()));
|
||||
s.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -542,11 +542,11 @@ namespace spot
|
|||
formula res = nullptr;
|
||||
for (auto v: aprops_)
|
||||
{
|
||||
formula f = formula::G(formula::F(v));
|
||||
if (res)
|
||||
res = formula::And({f, res});
|
||||
else
|
||||
res = f;
|
||||
formula f = formula::G(formula::F(v));
|
||||
if (res)
|
||||
res = formula::And({f, res});
|
||||
else
|
||||
res = f;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
random_formula(unsigned proba_size,
|
||||
const atomic_prop_set* ap):
|
||||
const atomic_prop_set* ap):
|
||||
proba_size_(proba_size), proba_(new op_proba[proba_size_]), ap_(ap)
|
||||
{
|
||||
}
|
||||
|
|
@ -125,23 +125,23 @@ namespace spot
|
|||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
F 1
|
||||
G 1
|
||||
X 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
R 1
|
||||
U 1
|
||||
W 1
|
||||
M 1
|
||||
and 1
|
||||
or 1
|
||||
\endverbatim */
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
F 1
|
||||
G 1
|
||||
X 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
R 1
|
||||
U 1
|
||||
W 1
|
||||
M 1
|
||||
and 1
|
||||
or 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where \c n is the number of atomic propositions in the
|
||||
/// set passed to the constructor.
|
||||
|
|
@ -176,16 +176,16 @@ namespace spot
|
|||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
and 1
|
||||
or 1
|
||||
\endverbatim */
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
and 1
|
||||
or 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where \c n is the number of atomic propositions in the
|
||||
/// set passed to the constructor.
|
||||
|
|
@ -215,18 +215,18 @@ namespace spot
|
|||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
eword 1
|
||||
boolform 1
|
||||
star 1
|
||||
star_b 1
|
||||
equal_b 1
|
||||
goto_b 1
|
||||
and 1
|
||||
andNLM 1
|
||||
or 1
|
||||
concat 1
|
||||
fusion 1
|
||||
\endverbatim */
|
||||
eword 1
|
||||
boolform 1
|
||||
star 1
|
||||
star_b 1
|
||||
equal_b 1
|
||||
goto_b 1
|
||||
and 1
|
||||
andNLM 1
|
||||
or 1
|
||||
concat 1
|
||||
fusion 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where "boolfrom" designates a Boolean formula generated
|
||||
/// by random_boolean.
|
||||
|
|
@ -260,26 +260,26 @@ namespace spot
|
|||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
F 1
|
||||
G 1
|
||||
X 1
|
||||
Closure 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
R 1
|
||||
U 1
|
||||
W 1
|
||||
M 1
|
||||
and 1
|
||||
or 1
|
||||
EConcat 1
|
||||
UConcat 1
|
||||
\endverbatim */
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
F 1
|
||||
G 1
|
||||
X 1
|
||||
Closure 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
R 1
|
||||
U 1
|
||||
W 1
|
||||
M 1
|
||||
and 1
|
||||
or 1
|
||||
EConcat 1
|
||||
UConcat 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where \c n is the number of atomic propositions in the
|
||||
/// set passed to the constructor.
|
||||
|
|
@ -306,14 +306,14 @@ namespace spot
|
|||
|
||||
public:
|
||||
randltlgenerator(int aprops_n, const option_map& opts,
|
||||
char* opt_pL = nullptr,
|
||||
char* opt_pS = nullptr,
|
||||
char* opt_pB = nullptr);
|
||||
char* opt_pL = nullptr,
|
||||
char* opt_pS = nullptr,
|
||||
char* opt_pB = nullptr);
|
||||
|
||||
randltlgenerator(atomic_prop_set aprops, const option_map& opts,
|
||||
char* opt_pL = nullptr,
|
||||
char* opt_pS = nullptr,
|
||||
char* opt_pB = nullptr);
|
||||
char* opt_pL = nullptr,
|
||||
char* opt_pS = nullptr,
|
||||
char* opt_pB = nullptr);
|
||||
|
||||
~randltlgenerator();
|
||||
|
||||
|
|
|
|||
|
|
@ -43,15 +43,15 @@ namespace spot
|
|||
{
|
||||
unsigned nn;
|
||||
pnn_generator()
|
||||
: nn(0)
|
||||
{
|
||||
}
|
||||
: nn(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual formula next() override
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << 'p' << nn++;
|
||||
return formula::ap(s.str());
|
||||
std::ostringstream s;
|
||||
s << 'p' << nn++;
|
||||
return formula::ap(s.str());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -59,23 +59,23 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
abc_generator()
|
||||
: nn(0)
|
||||
{
|
||||
}
|
||||
: nn(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned nn;
|
||||
|
||||
virtual formula next() override
|
||||
{
|
||||
std::string s;
|
||||
unsigned n = nn++;
|
||||
do
|
||||
{
|
||||
s.push_back('a' + (n % 26));
|
||||
n /= 26;
|
||||
}
|
||||
while (n);
|
||||
return formula::ap(s);
|
||||
std::string s;
|
||||
unsigned n = nn++;
|
||||
do
|
||||
{
|
||||
s.push_back('a' + (n % 26));
|
||||
n /= 26;
|
||||
}
|
||||
while (n);
|
||||
return formula::ap(s);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -89,42 +89,42 @@ namespace spot
|
|||
relabeling_map* oldnames;
|
||||
|
||||
relabeler(ap_generator* gen, relabeling_map* m)
|
||||
: gen(gen), oldnames(m)
|
||||
: gen(gen), oldnames(m)
|
||||
{
|
||||
}
|
||||
|
||||
~relabeler()
|
||||
{
|
||||
delete gen;
|
||||
delete gen;
|
||||
}
|
||||
|
||||
formula rename(formula old)
|
||||
{
|
||||
auto r = newname.emplace(old, nullptr);
|
||||
if (!r.second)
|
||||
{
|
||||
return r.first->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula res = gen->next();
|
||||
r.first->second = res;
|
||||
if (oldnames)
|
||||
(*oldnames)[res] = old;
|
||||
return res;
|
||||
}
|
||||
auto r = newname.emplace(old, nullptr);
|
||||
if (!r.second)
|
||||
{
|
||||
return r.first->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula res = gen->next();
|
||||
r.first->second = res;
|
||||
if (oldnames)
|
||||
(*oldnames)[res] = old;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
formula
|
||||
visit(formula f)
|
||||
{
|
||||
if (f.is(op::ap))
|
||||
return rename(f);
|
||||
else
|
||||
return f.map([this](formula f)
|
||||
{
|
||||
return this->visit(f);
|
||||
});
|
||||
if (f.is(op::ap))
|
||||
return rename(f);
|
||||
else
|
||||
return f.map([this](formula f)
|
||||
{
|
||||
return this->visit(f);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -139,11 +139,11 @@ namespace spot
|
|||
switch (style)
|
||||
{
|
||||
case Pnn:
|
||||
gen = new pnn_generator;
|
||||
break;
|
||||
gen = new pnn_generator;
|
||||
break;
|
||||
case Abc:
|
||||
gen = new abc_generator;
|
||||
break;
|
||||
gen = new abc_generator;
|
||||
break;
|
||||
}
|
||||
|
||||
relabeler r(gen, m);
|
||||
|
|
@ -236,67 +236,67 @@ namespace spot
|
|||
std::stack<formula> s;
|
||||
|
||||
formula_to_fgraph(fgraph& g):
|
||||
g(g)
|
||||
{
|
||||
}
|
||||
g(g)
|
||||
{
|
||||
}
|
||||
|
||||
~formula_to_fgraph()
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
visit(formula f)
|
||||
visit(formula f)
|
||||
{
|
||||
{
|
||||
// Connect to parent
|
||||
auto in = g.emplace(f, succ_vec());
|
||||
if (!s.empty())
|
||||
{
|
||||
formula top = s.top();
|
||||
in.first->second.push_back(top);
|
||||
g[top].push_back(f);
|
||||
if (!in.second)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(in.second);
|
||||
}
|
||||
}
|
||||
s.push(f);
|
||||
{
|
||||
// Connect to parent
|
||||
auto in = g.emplace(f, succ_vec());
|
||||
if (!s.empty())
|
||||
{
|
||||
formula top = s.top();
|
||||
in.first->second.push_back(top);
|
||||
g[top].push_back(f);
|
||||
if (!in.second)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(in.second);
|
||||
}
|
||||
}
|
||||
s.push(f);
|
||||
|
||||
unsigned sz = f.size();
|
||||
unsigned i = 0;
|
||||
if (sz > 2 && !f.is_boolean())
|
||||
{
|
||||
/// If we have a formula like (a & b & Xc), consider
|
||||
/// it as ((a & b) & Xc) in the graph to isolate the
|
||||
/// Boolean operands as a single node.
|
||||
formula b = f.boolean_operands(&i);
|
||||
if (b)
|
||||
visit(b);
|
||||
}
|
||||
for (; i < sz; ++i)
|
||||
visit(f[i]);
|
||||
if (sz > 1 && f.is_boolean())
|
||||
{
|
||||
// For Boolean nodes, connect all children in a
|
||||
// loop. This way the node can only be a cut-point
|
||||
// if it separates all children from the reset of
|
||||
// the graph (not only one).
|
||||
formula pred = f[0];
|
||||
for (i = 1; i < sz; ++i)
|
||||
{
|
||||
formula next = f[i];
|
||||
// Note that we only add an edge in one
|
||||
// direction, because we are building a cycle
|
||||
// between all children anyway.
|
||||
g[pred].push_back(next);
|
||||
pred = next;
|
||||
}
|
||||
g[pred].push_back(f[0]);
|
||||
}
|
||||
s.pop();
|
||||
unsigned sz = f.size();
|
||||
unsigned i = 0;
|
||||
if (sz > 2 && !f.is_boolean())
|
||||
{
|
||||
/// If we have a formula like (a & b & Xc), consider
|
||||
/// it as ((a & b) & Xc) in the graph to isolate the
|
||||
/// Boolean operands as a single node.
|
||||
formula b = f.boolean_operands(&i);
|
||||
if (b)
|
||||
visit(b);
|
||||
}
|
||||
for (; i < sz; ++i)
|
||||
visit(f[i]);
|
||||
if (sz > 1 && f.is_boolean())
|
||||
{
|
||||
// For Boolean nodes, connect all children in a
|
||||
// loop. This way the node can only be a cut-point
|
||||
// if it separates all children from the reset of
|
||||
// the graph (not only one).
|
||||
formula pred = f[0];
|
||||
for (i = 1; i < sz; ++i)
|
||||
{
|
||||
formula next = f[i];
|
||||
// Note that we only add an edge in one
|
||||
// direction, because we are building a cycle
|
||||
// between all children anyway.
|
||||
g[pred].push_back(next);
|
||||
pred = next;
|
||||
}
|
||||
g[pred].push_back(f[0]);
|
||||
}
|
||||
s.pop();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -307,7 +307,7 @@ namespace spot
|
|||
unsigned num; // serial number, in pre-order
|
||||
unsigned low; // lowest number accessible via unstacked descendants
|
||||
data_entry(unsigned num = 0, unsigned low = 0)
|
||||
: num(num), low(low)
|
||||
: num(num), low(low)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
@ -315,7 +315,7 @@ namespace spot
|
|||
struct stack_entry
|
||||
{
|
||||
formula grand_parent;
|
||||
formula parent; // current node
|
||||
formula parent; // current node
|
||||
succ_vec::const_iterator current_child;
|
||||
succ_vec::const_iterator last_child;
|
||||
};
|
||||
|
|
@ -347,58 +347,58 @@ namespace spot
|
|||
s.push(e);
|
||||
|
||||
while (!s.empty())
|
||||
{
|
||||
stack_entry& e = s.top();
|
||||
if (e.current_child != e.last_child)
|
||||
{
|
||||
// Skip the edge if it is just the reverse of the one
|
||||
// we took.
|
||||
formula child = *e.current_child;
|
||||
if (child == e.grand_parent)
|
||||
{
|
||||
++e.current_child;
|
||||
continue;
|
||||
}
|
||||
auto i = data.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(child),
|
||||
std::forward_as_tuple(num, num));
|
||||
if (i.second) // New destination.
|
||||
{
|
||||
++num;
|
||||
const succ_vec& children = g.find(child)->second;
|
||||
stack_entry newe = { e.parent, child,
|
||||
children.begin(), children.end() };
|
||||
s.push(newe);
|
||||
}
|
||||
else // Destination exists.
|
||||
{
|
||||
data_entry& dparent = data[e.parent];
|
||||
data_entry& dchild = i.first->second;
|
||||
// If this is a back-edge, update
|
||||
// the low field of the parent.
|
||||
if (dchild.num <= dparent.num)
|
||||
if (dparent.low > dchild.num)
|
||||
dparent.low = dchild.num;
|
||||
}
|
||||
++e.current_child;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula grand_parent = e.grand_parent;
|
||||
formula parent = e.parent;
|
||||
s.pop();
|
||||
if (!s.empty())
|
||||
{
|
||||
data_entry& dparent = data[parent];
|
||||
data_entry& dgrand_parent = data[grand_parent];
|
||||
if (dparent.low >= dgrand_parent.num // cut-point
|
||||
&& grand_parent.is_boolean())
|
||||
c.insert(grand_parent);
|
||||
if (dparent.low < dgrand_parent.low)
|
||||
dgrand_parent.low = dparent.low;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
stack_entry& e = s.top();
|
||||
if (e.current_child != e.last_child)
|
||||
{
|
||||
// Skip the edge if it is just the reverse of the one
|
||||
// we took.
|
||||
formula child = *e.current_child;
|
||||
if (child == e.grand_parent)
|
||||
{
|
||||
++e.current_child;
|
||||
continue;
|
||||
}
|
||||
auto i = data.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(child),
|
||||
std::forward_as_tuple(num, num));
|
||||
if (i.second) // New destination.
|
||||
{
|
||||
++num;
|
||||
const succ_vec& children = g.find(child)->second;
|
||||
stack_entry newe = { e.parent, child,
|
||||
children.begin(), children.end() };
|
||||
s.push(newe);
|
||||
}
|
||||
else // Destination exists.
|
||||
{
|
||||
data_entry& dparent = data[e.parent];
|
||||
data_entry& dchild = i.first->second;
|
||||
// If this is a back-edge, update
|
||||
// the low field of the parent.
|
||||
if (dchild.num <= dparent.num)
|
||||
if (dparent.low > dchild.num)
|
||||
dparent.low = dchild.num;
|
||||
}
|
||||
++e.current_child;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula grand_parent = e.grand_parent;
|
||||
formula parent = e.parent;
|
||||
s.pop();
|
||||
if (!s.empty())
|
||||
{
|
||||
data_entry& dparent = data[parent];
|
||||
data_entry& dgrand_parent = data[grand_parent];
|
||||
if (dparent.low >= dgrand_parent.num // cut-point
|
||||
&& grand_parent.is_boolean())
|
||||
c.insert(grand_parent);
|
||||
if (dparent.low < dgrand_parent.low)
|
||||
dgrand_parent.low = dparent.low;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -407,44 +407,44 @@ namespace spot
|
|||
public:
|
||||
fset& c;
|
||||
bse_relabeler(ap_generator* gen, fset& c,
|
||||
relabeling_map* m)
|
||||
: relabeler(gen, m), c(c)
|
||||
relabeling_map* m)
|
||||
: relabeler(gen, m), c(c)
|
||||
{
|
||||
}
|
||||
|
||||
using relabeler::visit;
|
||||
|
||||
formula
|
||||
visit(formula f)
|
||||
visit(formula f)
|
||||
{
|
||||
if (f.is(op::ap) || (c.find(f) != c.end()))
|
||||
return rename(f);
|
||||
if (f.is(op::ap) || (c.find(f) != c.end()))
|
||||
return rename(f);
|
||||
|
||||
unsigned sz = f.size();
|
||||
if (sz <= 2)
|
||||
return f.map([this](formula f)
|
||||
{
|
||||
return visit(f);
|
||||
});
|
||||
unsigned sz = f.size();
|
||||
if (sz <= 2)
|
||||
return f.map([this](formula f)
|
||||
{
|
||||
return visit(f);
|
||||
});
|
||||
|
||||
unsigned i = 0;
|
||||
std::vector<formula> res;
|
||||
/// If we have a formula like (a & b & Xc), consider
|
||||
/// it as ((a & b) & Xc) in the graph to isolate the
|
||||
/// Boolean operands as a single node.
|
||||
formula b = f.boolean_operands(&i);
|
||||
if (b)
|
||||
{
|
||||
res.reserve(sz - i + 1);
|
||||
res.push_back(visit(b));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.reserve(sz);
|
||||
}
|
||||
for (; i < sz; ++i)
|
||||
res.push_back(visit(f[i]));
|
||||
return formula::multop(f.kind(), res);
|
||||
unsigned i = 0;
|
||||
std::vector<formula> res;
|
||||
/// If we have a formula like (a & b & Xc), consider
|
||||
/// it as ((a & b) & Xc) in the graph to isolate the
|
||||
/// Boolean operands as a single node.
|
||||
formula b = f.boolean_operands(&i);
|
||||
if (b)
|
||||
{
|
||||
res.reserve(sz - i + 1);
|
||||
res.push_back(visit(b));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.reserve(sz);
|
||||
}
|
||||
for (; i < sz; ++i)
|
||||
res.push_back(visit(f[i]));
|
||||
return formula::multop(f.kind(), res);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -471,11 +471,11 @@ namespace spot
|
|||
switch (style)
|
||||
{
|
||||
case Pnn:
|
||||
gen = new pnn_generator;
|
||||
break;
|
||||
gen = new pnn_generator;
|
||||
break;
|
||||
case Abc:
|
||||
gen = new abc_generator;
|
||||
break;
|
||||
gen = new abc_generator;
|
||||
break;
|
||||
}
|
||||
bse_relabeler rel(gen, c, m);
|
||||
return rel.visit(f);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace spot
|
|||
/// between the new names (keys) and the old names (values).
|
||||
SPOT_API
|
||||
formula relabel(formula f, relabeling_style style,
|
||||
relabeling_map* m = nullptr);
|
||||
relabeling_map* m = nullptr);
|
||||
|
||||
|
||||
/// \ingroup tl_rewriting
|
||||
|
|
@ -47,5 +47,5 @@ namespace spot
|
|||
/// between the new names (keys) and the old names (values).
|
||||
SPOT_API
|
||||
formula relabel_bse(formula f, relabeling_style style,
|
||||
relabeling_map* m = nullptr);
|
||||
relabeling_map* m = nullptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,59 +29,59 @@ namespace spot
|
|||
remove_x_rec(formula f, atomic_prop_set& aps)
|
||||
{
|
||||
if (f.is_syntactic_stutter_invariant())
|
||||
return f;
|
||||
return f;
|
||||
|
||||
auto rec = [&aps](formula f)
|
||||
{
|
||||
return remove_x_rec(f, aps);
|
||||
};
|
||||
{
|
||||
return remove_x_rec(f, aps);
|
||||
};
|
||||
|
||||
if (!f.is(op::X))
|
||||
return f.map(rec);
|
||||
return f.map(rec);
|
||||
|
||||
formula c = rec(f[0]);
|
||||
|
||||
std::vector<formula> vo;
|
||||
for (auto i: aps)
|
||||
{
|
||||
// First line
|
||||
std::vector<formula> va1;
|
||||
formula npi = formula::Not(i);
|
||||
va1.push_back(i);
|
||||
va1.push_back(formula::U(i, formula::And({npi, c})));
|
||||
{
|
||||
// First line
|
||||
std::vector<formula> va1;
|
||||
formula npi = formula::Not(i);
|
||||
va1.push_back(i);
|
||||
va1.push_back(formula::U(i, formula::And({npi, c})));
|
||||
|
||||
for (auto j: aps)
|
||||
if (j != i)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::U(formula::Not(j), npi);
|
||||
va1.push_back(formula::Or({formula::U(j, npi), tmp}));
|
||||
}
|
||||
vo.push_back(formula::And(va1));
|
||||
// Second line
|
||||
std::vector<formula> va2;
|
||||
va2.push_back(npi);
|
||||
va2.push_back(formula::U(npi, formula::And({i, c})));
|
||||
for (auto j: aps)
|
||||
if (j != i)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::U(formula::Not(j), i);
|
||||
va2.push_back(formula::Or({formula::U(j, i), tmp}));
|
||||
}
|
||||
vo.push_back(formula::And(va2));
|
||||
}
|
||||
for (auto j: aps)
|
||||
if (j != i)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::U(formula::Not(j), npi);
|
||||
va1.push_back(formula::Or({formula::U(j, npi), tmp}));
|
||||
}
|
||||
vo.push_back(formula::And(va1));
|
||||
// Second line
|
||||
std::vector<formula> va2;
|
||||
va2.push_back(npi);
|
||||
va2.push_back(formula::U(npi, formula::And({i, c})));
|
||||
for (auto j: aps)
|
||||
if (j != i)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::U(formula::Not(j), i);
|
||||
va2.push_back(formula::Or({formula::U(j, i), tmp}));
|
||||
}
|
||||
vo.push_back(formula::And(va2));
|
||||
}
|
||||
// Third line
|
||||
std::vector<formula> va3;
|
||||
for (auto i: aps)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::G(formula::Not(i));
|
||||
va3.push_back(formula::Or({formula::G(i), tmp}));
|
||||
}
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::G(formula::Not(i));
|
||||
va3.push_back(formula::Or({formula::G(i), tmp}));
|
||||
}
|
||||
va3.push_back(c);
|
||||
vo.push_back(formula::And(va3));
|
||||
return formula::Or(vo);
|
||||
|
|
|
|||
5438
spot/tl/simplify.cc
5438
spot/tl/simplify.cc
File diff suppressed because it is too large
Load diff
|
|
@ -30,23 +30,23 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
tl_simplifier_options(bool basics = true,
|
||||
bool synt_impl = true,
|
||||
bool event_univ = true,
|
||||
bool containment_checks = false,
|
||||
bool containment_checks_stronger = false,
|
||||
bool nenoform_stop_on_boolean = false,
|
||||
bool reduce_size_strictly = false,
|
||||
bool boolean_to_isop = false,
|
||||
bool favor_event_univ = false)
|
||||
bool synt_impl = true,
|
||||
bool event_univ = true,
|
||||
bool containment_checks = false,
|
||||
bool containment_checks_stronger = false,
|
||||
bool nenoform_stop_on_boolean = false,
|
||||
bool reduce_size_strictly = false,
|
||||
bool boolean_to_isop = false,
|
||||
bool favor_event_univ = false)
|
||||
: reduce_basics(basics),
|
||||
synt_impl(synt_impl),
|
||||
event_univ(event_univ),
|
||||
containment_checks(containment_checks),
|
||||
containment_checks_stronger(containment_checks_stronger),
|
||||
nenoform_stop_on_boolean(nenoform_stop_on_boolean),
|
||||
reduce_size_strictly(reduce_size_strictly),
|
||||
boolean_to_isop(boolean_to_isop),
|
||||
favor_event_univ(favor_event_univ)
|
||||
synt_impl(synt_impl),
|
||||
event_univ(event_univ),
|
||||
containment_checks(containment_checks),
|
||||
containment_checks_stronger(containment_checks_stronger),
|
||||
nenoform_stop_on_boolean(nenoform_stop_on_boolean),
|
||||
reduce_size_strictly(reduce_size_strictly),
|
||||
boolean_to_isop(boolean_to_isop),
|
||||
favor_event_univ(favor_event_univ)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -54,21 +54,21 @@ namespace spot
|
|||
tl_simplifier_options(false, false, false)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case 3:
|
||||
containment_checks = true;
|
||||
containment_checks_stronger = true;
|
||||
// fall through
|
||||
case 2:
|
||||
synt_impl = true;
|
||||
// fall through
|
||||
case 1:
|
||||
reduce_basics = true;
|
||||
event_univ = true;
|
||||
// fall through
|
||||
default:
|
||||
break;
|
||||
}
|
||||
{
|
||||
case 3:
|
||||
containment_checks = true;
|
||||
containment_checks_stronger = true;
|
||||
// fall through
|
||||
case 2:
|
||||
synt_impl = true;
|
||||
// fall through
|
||||
case 1:
|
||||
reduce_basics = true;
|
||||
event_univ = true;
|
||||
// fall through
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool reduce_basics;
|
||||
|
|
@ -99,7 +99,7 @@ namespace spot
|
|||
public:
|
||||
tl_simplifier(const bdd_dict_ptr& dict = make_bdd_dict());
|
||||
tl_simplifier(const tl_simplifier_options& opt,
|
||||
bdd_dict_ptr dict = make_bdd_dict());
|
||||
bdd_dict_ptr dict = make_bdd_dict());
|
||||
~tl_simplifier();
|
||||
|
||||
/// Simplify the formula \a f (using options supplied to the
|
||||
|
|
@ -123,18 +123,18 @@ namespace spot
|
|||
///
|
||||
/// This is adapted from
|
||||
/** \verbatim
|
||||
@InProceedings{ somenzi.00.cav,
|
||||
author = {Fabio Somenzi and Roderick Bloem},
|
||||
title = {Efficient {B\"u}chi Automata for {LTL} Formulae},
|
||||
booktitle = {Proceedings of the 12th International Conference on
|
||||
Computer Aided Verification (CAV'00)},
|
||||
pages = {247--263},
|
||||
year = {2000},
|
||||
volume = {1855},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
publisher = {Springer-Verlag}
|
||||
}
|
||||
\endverbatim */
|
||||
@InProceedings{ somenzi.00.cav,
|
||||
author = {Fabio Somenzi and Roderick Bloem},
|
||||
title = {Efficient {B\"u}chi Automata for {LTL} Formulae},
|
||||
booktitle = {Proceedings of the 12th International Conference on
|
||||
Computer Aided Verification (CAV'00)},
|
||||
pages = {247--263},
|
||||
year = {2000},
|
||||
volume = {1855},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
publisher = {Springer-Verlag}
|
||||
}
|
||||
\endverbatim */
|
||||
///
|
||||
bool syntactic_implication(formula f, formula g);
|
||||
/// \brief Syntactic implication with one negated argument.
|
||||
|
|
@ -143,7 +143,7 @@ namespace spot
|
|||
/// \a f implies !\a g. If \a right is false, this returns
|
||||
/// whether !\a f implies \a g.
|
||||
bool syntactic_implication_neg(formula f, formula g,
|
||||
bool right);
|
||||
bool right);
|
||||
|
||||
/// \brief check whether two formulae are equivalent.
|
||||
///
|
||||
|
|
|
|||
164
spot/tl/snf.cc
164
spot/tl/snf.cc
|
|
@ -33,97 +33,97 @@ namespace spot
|
|||
snf_cache* cache_;
|
||||
public:
|
||||
snf_visitor(snf_cache* c)
|
||||
: cache_(c)
|
||||
: cache_(c)
|
||||
{
|
||||
}
|
||||
|
||||
formula visit(formula f)
|
||||
{
|
||||
if (!f.accepts_eword())
|
||||
return f;
|
||||
if (!f.accepts_eword())
|
||||
return f;
|
||||
|
||||
snf_cache::const_iterator i = cache_->find(f);
|
||||
if (i != cache_->end())
|
||||
return i->second;
|
||||
snf_cache::const_iterator i = cache_->find(f);
|
||||
if (i != cache_->end())
|
||||
return i->second;
|
||||
|
||||
formula out;
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::eword:
|
||||
out = formula::ff();
|
||||
break;
|
||||
case op::Star:
|
||||
if (!bounded)
|
||||
out = visit(f[0]); // Strip the star.
|
||||
else
|
||||
out = formula::Star(visit(f[0]),
|
||||
std::max(unsigned(f.min()), 1U), f.max());
|
||||
break;
|
||||
case op::Concat:
|
||||
if (bounded)
|
||||
{
|
||||
out = f;
|
||||
break;
|
||||
}
|
||||
// Fall through
|
||||
case op::OrRat:
|
||||
case op::AndNLM:
|
||||
// Let F designate expressions that accept [*0],
|
||||
// and G designate expressions that do not.
|
||||
formula out;
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::eword:
|
||||
out = formula::ff();
|
||||
break;
|
||||
case op::Star:
|
||||
if (!bounded)
|
||||
out = visit(f[0]); // Strip the star.
|
||||
else
|
||||
out = formula::Star(visit(f[0]),
|
||||
std::max(unsigned(f.min()), 1U), f.max());
|
||||
break;
|
||||
case op::Concat:
|
||||
if (bounded)
|
||||
{
|
||||
out = f;
|
||||
break;
|
||||
}
|
||||
// Fall through
|
||||
case op::OrRat:
|
||||
case op::AndNLM:
|
||||
// Let F designate expressions that accept [*0],
|
||||
// and G designate expressions that do not.
|
||||
|
||||
// (G₁;G₂;G₃)° = G₁;G₂;G₃
|
||||
// (G₁;F₂;G₃)° = (G₁°);F₂;(G₃°) = G₁;F₂;G₃
|
||||
// because there is nothing to do recursively on a G.
|
||||
//
|
||||
// AndNLM can be dealt with similarly.
|
||||
//
|
||||
// The above cases are already handled by the
|
||||
// accepts_eword() tests at the top of this method. So
|
||||
// we reach this switch, we only have to deal with...
|
||||
//
|
||||
// (F₁;F₂;F₃)° = (F₁°)|(F₂°)|(F₃°)
|
||||
// (F₁&F₂&F₃)° = (F₁°)|(F₂°)|(F₃°)
|
||||
// (F₁|G₂|F₃)° = (F₁°)|(G₂°)|(F₃°)
|
||||
{
|
||||
unsigned s = f.size();
|
||||
std::vector<formula> v;
|
||||
v.reserve(s);
|
||||
for (unsigned pos = 0; pos < s; ++pos)
|
||||
v.emplace_back(visit(f[pos]));
|
||||
out = formula::OrRat(v);
|
||||
break;
|
||||
}
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
case op::Fusion:
|
||||
case op::Or:
|
||||
case op::And:
|
||||
SPOT_UNREACHABLE();
|
||||
case op::AndRat: // Can AndRat be handled better?
|
||||
case op::FStar: // Can FStar be handled better?
|
||||
out = f;
|
||||
break;
|
||||
}
|
||||
// (G₁;G₂;G₃)° = G₁;G₂;G₃
|
||||
// (G₁;F₂;G₃)° = (G₁°);F₂;(G₃°) = G₁;F₂;G₃
|
||||
// because there is nothing to do recursively on a G.
|
||||
//
|
||||
// AndNLM can be dealt with similarly.
|
||||
//
|
||||
// The above cases are already handled by the
|
||||
// accepts_eword() tests at the top of this method. So
|
||||
// we reach this switch, we only have to deal with...
|
||||
//
|
||||
// (F₁;F₂;F₃)° = (F₁°)|(F₂°)|(F₃°)
|
||||
// (F₁&F₂&F₃)° = (F₁°)|(F₂°)|(F₃°)
|
||||
// (F₁|G₂|F₃)° = (F₁°)|(G₂°)|(F₃°)
|
||||
{
|
||||
unsigned s = f.size();
|
||||
std::vector<formula> v;
|
||||
v.reserve(s);
|
||||
for (unsigned pos = 0; pos < s; ++pos)
|
||||
v.emplace_back(visit(f[pos]));
|
||||
out = formula::OrRat(v);
|
||||
break;
|
||||
}
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
case op::Fusion:
|
||||
case op::Or:
|
||||
case op::And:
|
||||
SPOT_UNREACHABLE();
|
||||
case op::AndRat: // Can AndRat be handled better?
|
||||
case op::FStar: // Can FStar be handled better?
|
||||
out = f;
|
||||
break;
|
||||
}
|
||||
|
||||
return (*cache_)[f] = out;
|
||||
return (*cache_)[f] = out;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ namespace spot
|
|||
/// paper.
|
||||
///
|
||||
/** \verbatim
|
||||
@Article{ bruggeman.96.tcs,
|
||||
author = {Anne Br{\"u}ggemann-Klein},
|
||||
title = {Regular Expressions into Finite Automata},
|
||||
journal = {Theoretical Computer Science},
|
||||
year = {1996},
|
||||
volume = {120},
|
||||
pages = {87--98}
|
||||
@Article{ bruggeman.96.tcs,
|
||||
author = {Anne Br{\"u}ggemann-Klein},
|
||||
title = {Regular Expressions into Finite Automata},
|
||||
journal = {Theoretical Computer Science},
|
||||
year = {1996},
|
||||
volume = {120},
|
||||
pages = {87--98}
|
||||
}
|
||||
\endverbatim */
|
||||
///
|
||||
|
|
|
|||
|
|
@ -26,44 +26,44 @@ namespace spot
|
|||
{
|
||||
while (*opt)
|
||||
switch (char c = *opt++)
|
||||
{
|
||||
case 'e':
|
||||
re_e_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
case 'F':
|
||||
re_f_ = true;
|
||||
re_some_f_g_ = true;
|
||||
break;
|
||||
case 'G':
|
||||
re_g_ = true;
|
||||
re_some_f_g_ = true;
|
||||
break;
|
||||
case 'i':
|
||||
re_i_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
case 'M':
|
||||
re_m_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case 'R':
|
||||
re_r_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case 'W':
|
||||
re_w_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case '^':
|
||||
re_xor_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error
|
||||
(std::string("unknown unabbreviation option: ")
|
||||
+ c);
|
||||
}
|
||||
{
|
||||
case 'e':
|
||||
re_e_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
case 'F':
|
||||
re_f_ = true;
|
||||
re_some_f_g_ = true;
|
||||
break;
|
||||
case 'G':
|
||||
re_g_ = true;
|
||||
re_some_f_g_ = true;
|
||||
break;
|
||||
case 'i':
|
||||
re_i_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
case 'M':
|
||||
re_m_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case 'R':
|
||||
re_r_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case 'W':
|
||||
re_w_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case '^':
|
||||
re_xor_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error
|
||||
(std::string("unknown unabbreviation option: ")
|
||||
+ c);
|
||||
}
|
||||
}
|
||||
|
||||
formula unabbreviator::run(formula in)
|
||||
|
|
@ -76,12 +76,12 @@ namespace spot
|
|||
bool no_boolean_rewrite = !re_some_bool_ || in.is_sugar_free_boolean();
|
||||
bool no_f_g_rewrite = !re_some_f_g_ || in.is_sugar_free_ltl();
|
||||
if (no_boolean_rewrite
|
||||
&& (in.is_boolean() || (no_f_g_rewrite && !re_some_other_)))
|
||||
&& (in.is_boolean() || (no_f_g_rewrite && !re_some_other_)))
|
||||
return entry.first->second = in;
|
||||
|
||||
auto rec = [this](formula f)
|
||||
{
|
||||
return this->run(f);
|
||||
return this->run(f);
|
||||
};
|
||||
|
||||
formula out = in;
|
||||
|
|
@ -112,132 +112,132 @@ namespace spot
|
|||
case op::Fusion:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
break;
|
||||
break;
|
||||
case op::F:
|
||||
// F f = true U f
|
||||
if (!re_f_)
|
||||
break;
|
||||
out = formula::U(formula::tt(), out[0]);
|
||||
break;
|
||||
// F f = true U f
|
||||
if (!re_f_)
|
||||
break;
|
||||
out = formula::U(formula::tt(), out[0]);
|
||||
break;
|
||||
case op::G:
|
||||
// G f = false R f
|
||||
// G f = f W false
|
||||
// G f = !F!f
|
||||
// G f = !(true U !f)
|
||||
if (!re_g_)
|
||||
break;
|
||||
if (!re_r_)
|
||||
{
|
||||
out = formula::R(formula::ff(), out[0]);
|
||||
break;
|
||||
}
|
||||
if (!re_w_)
|
||||
{
|
||||
out = formula::W(out[0], formula::ff());
|
||||
break;
|
||||
}
|
||||
{
|
||||
auto nc = formula::Not(out[0]);
|
||||
if (!re_f_)
|
||||
{
|
||||
out = formula::Not(formula::F(nc));
|
||||
break;
|
||||
}
|
||||
out = formula::Not(formula::U(formula::tt(), nc));
|
||||
break;
|
||||
}
|
||||
// G f = false R f
|
||||
// G f = f W false
|
||||
// G f = !F!f
|
||||
// G f = !(true U !f)
|
||||
if (!re_g_)
|
||||
break;
|
||||
if (!re_r_)
|
||||
{
|
||||
out = formula::R(formula::ff(), out[0]);
|
||||
break;
|
||||
}
|
||||
if (!re_w_)
|
||||
{
|
||||
out = formula::W(out[0], formula::ff());
|
||||
break;
|
||||
}
|
||||
{
|
||||
auto nc = formula::Not(out[0]);
|
||||
if (!re_f_)
|
||||
{
|
||||
out = formula::Not(formula::F(nc));
|
||||
break;
|
||||
}
|
||||
out = formula::Not(formula::U(formula::tt(), nc));
|
||||
break;
|
||||
}
|
||||
case op::Xor:
|
||||
// f1 ^ f2 == !(f1 <-> f2)
|
||||
// f1 ^ f2 == (f1 & !f2) | (f2 & !f1)
|
||||
if (!re_xor_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
if (!re_e_)
|
||||
{
|
||||
out = formula::Not(formula::Equiv(f1, f2));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto a = formula::And({f1, formula::Not(f2)});
|
||||
auto b = formula::And({f2, formula::Not(f1)});
|
||||
out = formula::Or({a, b});
|
||||
}
|
||||
}
|
||||
break;
|
||||
// f1 ^ f2 == !(f1 <-> f2)
|
||||
// f1 ^ f2 == (f1 & !f2) | (f2 & !f1)
|
||||
if (!re_xor_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
if (!re_e_)
|
||||
{
|
||||
out = formula::Not(formula::Equiv(f1, f2));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto a = formula::And({f1, formula::Not(f2)});
|
||||
auto b = formula::And({f2, formula::Not(f1)});
|
||||
out = formula::Or({a, b});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case op::Implies:
|
||||
// f1 => f2 == !f1 | f2
|
||||
if (!re_i_)
|
||||
break;
|
||||
out = formula::Or({formula::Not(out[0]), out[1]});
|
||||
break;
|
||||
// f1 => f2 == !f1 | f2
|
||||
if (!re_i_)
|
||||
break;
|
||||
out = formula::Or({formula::Not(out[0]), out[1]});
|
||||
break;
|
||||
case op::Equiv:
|
||||
// f1 <=> f2 == (f1 & f2) | (!f1 & !f2)
|
||||
if (!re_e_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
auto nf1 = formula::Not(f1);
|
||||
auto nf2 = formula::Not(f2);
|
||||
auto term1 = formula::And({f1, f2});
|
||||
auto term2 = formula::And({nf1, nf2});
|
||||
out = formula::Or({term1, term2});
|
||||
break;
|
||||
}
|
||||
// f1 <=> f2 == (f1 & f2) | (!f1 & !f2)
|
||||
if (!re_e_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
auto nf1 = formula::Not(f1);
|
||||
auto nf2 = formula::Not(f2);
|
||||
auto term1 = formula::And({f1, f2});
|
||||
auto term2 = formula::And({nf1, nf2});
|
||||
out = formula::Or({term1, term2});
|
||||
break;
|
||||
}
|
||||
case op::R:
|
||||
// f1 R f2 = f2 W (f1 & f2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | Gf2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | !F!f2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | !(1 U !f2))
|
||||
if (!re_r_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
auto f12 = formula::And({f1, f2});
|
||||
if (!re_w_)
|
||||
{
|
||||
out = formula::W(f2, f12);
|
||||
break;
|
||||
}
|
||||
auto gf2 = formula::G(f2);
|
||||
if (re_g_)
|
||||
gf2 = run(gf2);
|
||||
out = formula::U(f2, formula::Or({f12, gf2}));
|
||||
break;
|
||||
}
|
||||
// f1 R f2 = f2 W (f1 & f2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | Gf2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | !F!f2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | !(1 U !f2))
|
||||
if (!re_r_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
auto f12 = formula::And({f1, f2});
|
||||
if (!re_w_)
|
||||
{
|
||||
out = formula::W(f2, f12);
|
||||
break;
|
||||
}
|
||||
auto gf2 = formula::G(f2);
|
||||
if (re_g_)
|
||||
gf2 = run(gf2);
|
||||
out = formula::U(f2, formula::Or({f12, gf2}));
|
||||
break;
|
||||
}
|
||||
case op::W:
|
||||
// f1 W f2 = f2 R (f2 | f1)
|
||||
// f1 W f2 = f1 U (f2 | G f1)
|
||||
// f1 W f2 = f1 U (f2 | !F !f1)
|
||||
// f1 W f2 = f1 U (f2 | !(1 U !f1))
|
||||
if (!re_w_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
if (!re_r_)
|
||||
{
|
||||
out = formula::R(f2, formula::Or({f2, f1}));
|
||||
break;
|
||||
}
|
||||
auto gf1 = formula::G(f1);
|
||||
if (re_g_)
|
||||
gf1 = run(gf1);
|
||||
out = formula::U(f1, formula::Or({f2, gf1}));
|
||||
break;
|
||||
}
|
||||
// f1 W f2 = f2 R (f2 | f1)
|
||||
// f1 W f2 = f1 U (f2 | G f1)
|
||||
// f1 W f2 = f1 U (f2 | !F !f1)
|
||||
// f1 W f2 = f1 U (f2 | !(1 U !f1))
|
||||
if (!re_w_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
if (!re_r_)
|
||||
{
|
||||
out = formula::R(f2, formula::Or({f2, f1}));
|
||||
break;
|
||||
}
|
||||
auto gf1 = formula::G(f1);
|
||||
if (re_g_)
|
||||
gf1 = run(gf1);
|
||||
out = formula::U(f1, formula::Or({f2, gf1}));
|
||||
break;
|
||||
}
|
||||
case op::M:
|
||||
// f1 M f2 = f2 U (g2 & f1)
|
||||
if (!re_m_)
|
||||
break;
|
||||
{
|
||||
auto f2 = out[1];
|
||||
out = formula::U(f2, formula::And({f2, out[0]}));
|
||||
break;
|
||||
}
|
||||
// f1 M f2 = f2 U (g2 & f1)
|
||||
if (!re_m_)
|
||||
break;
|
||||
{
|
||||
auto f2 = out[1];
|
||||
out = formula::U(f2, formula::And({f2, out[0]}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return entry.first->second = out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ namespace spot
|
|||
bool re_r_ = false;
|
||||
bool re_w_ = false;
|
||||
bool re_xor_ = false;
|
||||
bool re_some_bool_ = false; // rewrite xor, i, or e
|
||||
bool re_some_f_g_ = false; // rewrite F or G
|
||||
bool re_some_other_ = false; // rewrite W, M, or R
|
||||
bool re_some_bool_ = false; // rewrite xor, i, or e
|
||||
bool re_some_f_g_ = false; // rewrite F or G
|
||||
bool re_some_other_ = false; // rewrite W, M, or R
|
||||
// Cache of rewritten subformulas
|
||||
std::unordered_map<formula, formula> cache_;
|
||||
public:
|
||||
|
|
|
|||
1660
spot/twa/acc.cc
1660
spot/twa/acc.cc
File diff suppressed because it is too large
Load diff
1004
spot/twa/acc.hh
1004
spot/twa/acc.hh
File diff suppressed because it is too large
Load diff
|
|
@ -50,21 +50,21 @@ namespace spot
|
|||
// a hash; but we should ensure that no object in the hash is
|
||||
// constructed with p==0.
|
||||
anon_free_list(bdd_dict_priv* p = nullptr)
|
||||
: priv_(p)
|
||||
: priv_(p)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int
|
||||
extend(int n) override
|
||||
{
|
||||
assert(priv_);
|
||||
int b = priv_->allocate_variables(n);
|
||||
free_anonymous_list_of_type::iterator i;
|
||||
for (i = priv_->free_anonymous_list_of.begin();
|
||||
i != priv_->free_anonymous_list_of.end(); ++i)
|
||||
if (&i->second != this)
|
||||
i->second.insert(b, n);
|
||||
return b;
|
||||
assert(priv_);
|
||||
int b = priv_->allocate_variables(n);
|
||||
free_anonymous_list_of_type::iterator i;
|
||||
for (i = priv_->free_anonymous_list_of.begin();
|
||||
i != priv_->free_anonymous_list_of.end(); ++i)
|
||||
if (&i->second != this)
|
||||
i->second.insert(b, n);
|
||||
return b;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -102,15 +102,15 @@ namespace spot
|
|||
fv_map::iterator sii = var_map.find(f);
|
||||
if (sii != var_map.end())
|
||||
{
|
||||
num = sii->second;
|
||||
num = sii->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
num = priv_->allocate_variables(1);
|
||||
var_map[f] = num;
|
||||
bdd_map.resize(bdd_varnum());
|
||||
bdd_map[num].type = var;
|
||||
bdd_map[num].f = f;
|
||||
num = priv_->allocate_variables(1);
|
||||
var_map[f] = num;
|
||||
bdd_map.resize(bdd_varnum());
|
||||
bdd_map[num].type = var;
|
||||
bdd_map[num].f = f;
|
||||
}
|
||||
bdd_map[num].refs.insert(for_me);
|
||||
return num;
|
||||
|
|
@ -118,7 +118,7 @@ namespace spot
|
|||
|
||||
int
|
||||
bdd_dict::has_registered_proposition(formula f,
|
||||
const void* me)
|
||||
const void* me)
|
||||
{
|
||||
auto ssi = var_map.find(f);
|
||||
if (ssi == var_map.end())
|
||||
|
|
@ -132,24 +132,24 @@ namespace spot
|
|||
|
||||
int
|
||||
bdd_dict::register_acceptance_variable(formula f,
|
||||
const void* for_me)
|
||||
const void* for_me)
|
||||
{
|
||||
int num;
|
||||
// Do not build an acceptance variable that already exists.
|
||||
fv_map::iterator sii = acc_map.find(f);
|
||||
if (sii != acc_map.end())
|
||||
{
|
||||
num = sii->second;
|
||||
num = sii->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
num = priv_->allocate_variables(1);
|
||||
acc_map[f] = num;
|
||||
bdd_map.resize(bdd_varnum());
|
||||
bdd_info& i = bdd_map[num];
|
||||
i.type = acc;
|
||||
i.f = f;
|
||||
i.clone_counts = 0;
|
||||
num = priv_->allocate_variables(1);
|
||||
acc_map[f] = num;
|
||||
bdd_map.resize(bdd_varnum());
|
||||
bdd_info& i = bdd_map[num];
|
||||
i.type = acc;
|
||||
i.f = f;
|
||||
i.clone_counts = 0;
|
||||
}
|
||||
bdd_map[num].refs.insert(for_me);
|
||||
return num;
|
||||
|
|
@ -163,9 +163,9 @@ namespace spot
|
|||
|
||||
if (i == priv_->free_anonymous_list_of.end())
|
||||
{
|
||||
i = (priv_->free_anonymous_list_of.insert
|
||||
(fal::value_type(for_me,
|
||||
priv_->free_anonymous_list_of[nullptr]))).first;
|
||||
i = (priv_->free_anonymous_list_of.insert
|
||||
(fal::value_type(for_me,
|
||||
priv_->free_anonymous_list_of[nullptr]))).first;
|
||||
}
|
||||
int res = i->second.register_n(n);
|
||||
|
||||
|
|
@ -173,8 +173,8 @@ namespace spot
|
|||
|
||||
while (n--)
|
||||
{
|
||||
bdd_map[res + n].type = anon;
|
||||
bdd_map[res + n].refs.insert(for_me);
|
||||
bdd_map[res + n].type = anon;
|
||||
bdd_map[res + n].refs.insert(for_me);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
|
@ -183,7 +183,7 @@ namespace spot
|
|||
|
||||
void
|
||||
bdd_dict::register_all_variables_of(const void* from_other,
|
||||
const void* for_me)
|
||||
const void* for_me)
|
||||
{
|
||||
auto j = priv_->free_anonymous_list_of.find(from_other);
|
||||
if (j != priv_->free_anonymous_list_of.end())
|
||||
|
|
@ -191,24 +191,24 @@ namespace spot
|
|||
|
||||
for (auto& i: bdd_map)
|
||||
{
|
||||
ref_set& s = i.refs;
|
||||
if (s.find(from_other) != s.end())
|
||||
s.insert(for_me);
|
||||
ref_set& s = i.refs;
|
||||
if (s.find(from_other) != s.end())
|
||||
s.insert(for_me);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
bdd_dict::register_all_propositions_of(const void* from_other,
|
||||
const void* for_me)
|
||||
const void* for_me)
|
||||
{
|
||||
for (auto& i: bdd_map)
|
||||
{
|
||||
if (i.type != var_type::var)
|
||||
continue;
|
||||
ref_set& s = i.refs;
|
||||
if (s.find(from_other) != s.end())
|
||||
s.insert(for_me);
|
||||
if (i.type != var_type::var)
|
||||
continue;
|
||||
ref_set& s = i.refs;
|
||||
if (s.find(from_other) != s.end())
|
||||
s.insert(for_me);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -241,24 +241,24 @@ namespace spot
|
|||
switch (bdd_map[v].type)
|
||||
{
|
||||
case var:
|
||||
f = bdd_map[v].f;
|
||||
var_map.erase(f);
|
||||
break;
|
||||
f = bdd_map[v].f;
|
||||
var_map.erase(f);
|
||||
break;
|
||||
case acc:
|
||||
f = bdd_map[v].f;
|
||||
acc_map.erase(f);
|
||||
break;
|
||||
f = bdd_map[v].f;
|
||||
acc_map.erase(f);
|
||||
break;
|
||||
case anon:
|
||||
{
|
||||
bdd_dict_priv::free_anonymous_list_of_type::iterator i;
|
||||
// Nobody use this variable as an anonymous variable
|
||||
// anymore, so remove it entirely from the anonymous
|
||||
// free list so it can be used for something else.
|
||||
for (i = priv_->free_anonymous_list_of.begin();
|
||||
i != priv_->free_anonymous_list_of.end(); ++i)
|
||||
i->second.remove(v, n);
|
||||
break;
|
||||
}
|
||||
{
|
||||
bdd_dict_priv::free_anonymous_list_of_type::iterator i;
|
||||
// Nobody use this variable as an anonymous variable
|
||||
// anymore, so remove it entirely from the anonymous
|
||||
// free list so it can be used for something else.
|
||||
for (i = priv_->free_anonymous_list_of.begin();
|
||||
i != priv_->free_anonymous_list_of.end(); ++i)
|
||||
i->second.remove(v, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Actually release the associated BDD variables, and the
|
||||
// formula itself.
|
||||
|
|
@ -283,39 +283,39 @@ namespace spot
|
|||
unsigned s = bdd_map.size();
|
||||
for (unsigned i = 0; i < s; ++i)
|
||||
{
|
||||
os << ' ' << i << ' ';
|
||||
const bdd_info& r = bdd_map[i];
|
||||
switch (r.type)
|
||||
{
|
||||
case anon:
|
||||
os << (r.refs.empty() ? "Free" : "Anon");
|
||||
break;
|
||||
case acc:
|
||||
os << "Acc[";
|
||||
print_psl(os, r.f) << ']';
|
||||
break;
|
||||
case var:
|
||||
os << "Var[";
|
||||
print_psl(os, r.f) << ']';
|
||||
break;
|
||||
}
|
||||
if (!r.refs.empty())
|
||||
{
|
||||
os << " x" << r.refs.size() << " {";
|
||||
for (ref_set::const_iterator si = r.refs.begin();
|
||||
si != r.refs.end(); ++si)
|
||||
os << ' ' << *si;
|
||||
os << " }";
|
||||
}
|
||||
os << '\n';
|
||||
os << ' ' << i << ' ';
|
||||
const bdd_info& r = bdd_map[i];
|
||||
switch (r.type)
|
||||
{
|
||||
case anon:
|
||||
os << (r.refs.empty() ? "Free" : "Anon");
|
||||
break;
|
||||
case acc:
|
||||
os << "Acc[";
|
||||
print_psl(os, r.f) << ']';
|
||||
break;
|
||||
case var:
|
||||
os << "Var[";
|
||||
print_psl(os, r.f) << ']';
|
||||
break;
|
||||
}
|
||||
if (!r.refs.empty())
|
||||
{
|
||||
os << " x" << r.refs.size() << " {";
|
||||
for (ref_set::const_iterator si = r.refs.begin();
|
||||
si != r.refs.end(); ++si)
|
||||
os << ' ' << *si;
|
||||
os << " }";
|
||||
}
|
||||
os << '\n';
|
||||
}
|
||||
os << "Anonymous lists:\n";
|
||||
bdd_dict_priv::free_anonymous_list_of_type::const_iterator ai;
|
||||
for (ai = priv_->free_anonymous_list_of.begin();
|
||||
ai != priv_->free_anonymous_list_of.end(); ++ai)
|
||||
ai != priv_->free_anonymous_list_of.end(); ++ai)
|
||||
{
|
||||
os << " [" << ai->first << "] ";
|
||||
ai->second.dump_free_list(os) << std::endl;
|
||||
os << " [" << ai->first << "] ";
|
||||
ai->second.dump_free_list(os) << std::endl;
|
||||
}
|
||||
os << "Free list:\n";
|
||||
priv_->dump_free_list(os);
|
||||
|
|
@ -334,42 +334,42 @@ namespace spot
|
|||
unsigned s = bdd_map.size();
|
||||
for (unsigned i = 0; i < s; ++i)
|
||||
{
|
||||
switch (bdd_map[i].type)
|
||||
{
|
||||
case var:
|
||||
var_seen = true;
|
||||
break;
|
||||
case acc:
|
||||
acc_seen = true;
|
||||
break;
|
||||
case anon:
|
||||
break;
|
||||
}
|
||||
refs_seen |= !bdd_map[i].refs.empty();
|
||||
switch (bdd_map[i].type)
|
||||
{
|
||||
case var:
|
||||
var_seen = true;
|
||||
break;
|
||||
case acc:
|
||||
acc_seen = true;
|
||||
break;
|
||||
case anon:
|
||||
break;
|
||||
}
|
||||
refs_seen |= !bdd_map[i].refs.empty();
|
||||
}
|
||||
if (var_map.empty() && acc_map.empty())
|
||||
{
|
||||
if (var_seen)
|
||||
{
|
||||
std::cerr << "var_map is empty but Var in map" << std::endl;
|
||||
fail = true;
|
||||
}
|
||||
if (acc_seen)
|
||||
{
|
||||
std::cerr << "acc_map is empty but Acc in map" << std::endl;
|
||||
fail = true;
|
||||
}
|
||||
if (refs_seen)
|
||||
{
|
||||
std::cerr << "maps are empty but var_refs is not" << std::endl;
|
||||
fail = true;
|
||||
}
|
||||
if (!fail)
|
||||
return;
|
||||
if (var_seen)
|
||||
{
|
||||
std::cerr << "var_map is empty but Var in map" << std::endl;
|
||||
fail = true;
|
||||
}
|
||||
if (acc_seen)
|
||||
{
|
||||
std::cerr << "acc_map is empty but Acc in map" << std::endl;
|
||||
fail = true;
|
||||
}
|
||||
if (refs_seen)
|
||||
{
|
||||
std::cerr << "maps are empty but var_refs is not" << std::endl;
|
||||
fail = true;
|
||||
}
|
||||
if (!fail)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "some maps are not empty" << std::endl;
|
||||
std::cerr << "some maps are not empty" << std::endl;
|
||||
}
|
||||
dump(std::cerr);
|
||||
abort();
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ namespace spot
|
|||
/// BDD-variable-to-formula maps.
|
||||
typedef std::map<int, formula> vf_map;
|
||||
|
||||
fv_map var_map; ///< Maps atomic propositions to BDD variables
|
||||
fv_map acc_map; ///< Maps acceptance conditions to BDD variables
|
||||
fv_map var_map; ///< Maps atomic propositions to BDD variables
|
||||
fv_map acc_map; ///< Maps acceptance conditions to BDD variables
|
||||
|
||||
/// BDD-variable reference counts.
|
||||
typedef std::set<const void*> ref_set;
|
||||
|
|
@ -80,7 +80,7 @@ namespace spot
|
|||
struct bdd_info {
|
||||
bdd_info() : type(anon) {}
|
||||
var_type type;
|
||||
formula f; // Used unless t==anon.
|
||||
formula f; // Used unless t==anon.
|
||||
ref_set refs;
|
||||
int clone_counts;
|
||||
};
|
||||
|
|
@ -180,21 +180,21 @@ namespace spot
|
|||
|
||||
template <typename T>
|
||||
void register_all_variables_of(const void* from_other,
|
||||
std::shared_ptr<T> for_me)
|
||||
std::shared_ptr<T> for_me)
|
||||
{
|
||||
register_all_variables_of(from_other, for_me.get());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void register_all_variables_of(std::shared_ptr<T> from_other,
|
||||
const void* for_me)
|
||||
const void* for_me)
|
||||
{
|
||||
register_all_variables_of(from_other.get(), for_me);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void register_all_variables_of(std::shared_ptr<T> from_other,
|
||||
std::shared_ptr<U> for_me)
|
||||
std::shared_ptr<U> for_me)
|
||||
{
|
||||
register_all_variables_of(from_other.get(), for_me.get());
|
||||
}
|
||||
|
|
@ -209,25 +209,25 @@ namespace spot
|
|||
/// is still alive.
|
||||
/// @{
|
||||
void register_all_propositions_of(const void* from_other,
|
||||
const void* for_me);
|
||||
const void* for_me);
|
||||
|
||||
template <typename T>
|
||||
void register_all_propositions_of(const void* from_other,
|
||||
std::shared_ptr<T> for_me)
|
||||
std::shared_ptr<T> for_me)
|
||||
{
|
||||
register_all_propositions_of(from_other, for_me.get());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void register_all_propositions_of(std::shared_ptr<T> from_other,
|
||||
const void* for_me)
|
||||
const void* for_me)
|
||||
{
|
||||
register_all_propositions_of(from_other.get(), for_me);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void register_all_propositions_of(std::shared_ptr<T> from_other,
|
||||
std::shared_ptr<U> for_me)
|
||||
std::shared_ptr<U> for_me)
|
||||
{
|
||||
register_all_propositions_of(from_other.get(), for_me.get());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,22 +58,22 @@ namespace spot
|
|||
switch (ref.type)
|
||||
{
|
||||
case bdd_dict::var:
|
||||
print_(o, ref.f);
|
||||
break;
|
||||
print_(o, ref.f);
|
||||
break;
|
||||
case bdd_dict::acc:
|
||||
if (want_acc)
|
||||
{
|
||||
o << "Acc[";
|
||||
print_(o, ref.f) << ']';
|
||||
}
|
||||
else
|
||||
{
|
||||
o << '"';
|
||||
print_(o, ref.f) << '"';
|
||||
}
|
||||
break;
|
||||
if (want_acc)
|
||||
{
|
||||
o << "Acc[";
|
||||
print_(o, ref.f) << ']';
|
||||
}
|
||||
else
|
||||
{
|
||||
o << '"';
|
||||
print_(o, ref.f) << '"';
|
||||
}
|
||||
break;
|
||||
case bdd_dict::anon:
|
||||
o << '?' << v;
|
||||
o << '?' << v;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,15 +85,15 @@ namespace spot
|
|||
bool not_first = false;
|
||||
for (int v = 0; v < size; ++v)
|
||||
{
|
||||
if (varset[v] < 0)
|
||||
continue;
|
||||
if (not_first)
|
||||
*where << ' ';
|
||||
else
|
||||
not_first = true;
|
||||
if (varset[v] == 0)
|
||||
*where << "! ";
|
||||
print_handler(*where, v);
|
||||
if (varset[v] < 0)
|
||||
continue;
|
||||
if (not_first)
|
||||
*where << ' ';
|
||||
else
|
||||
not_first = true;
|
||||
if (varset[v] == 0)
|
||||
*where << "! ";
|
||||
print_handler(*where, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,11 +114,11 @@ namespace spot
|
|||
{
|
||||
for (int v = 0; v < size; ++v)
|
||||
if (varset[v] > 0)
|
||||
{
|
||||
*where << (first_done ? ", " : "{");
|
||||
print_handler(*where, v);
|
||||
first_done = true;
|
||||
}
|
||||
{
|
||||
*where << (first_done ? ", " : "{");
|
||||
print_handler(*where, v);
|
||||
first_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
|
|
|
|||
|
|
@ -33,30 +33,30 @@ namespace spot
|
|||
conj_to_formula(bdd b, const bdd_dict_ptr d)
|
||||
{
|
||||
if (b == bddfalse)
|
||||
return formula::ff();
|
||||
return formula::ff();
|
||||
std::vector<formula> v;
|
||||
while (b != bddtrue)
|
||||
{
|
||||
int var = bdd_var(b);
|
||||
const bdd_dict::bdd_info& i = d->bdd_map[var];
|
||||
assert(i.type == bdd_dict::var);
|
||||
formula res = i.f;
|
||||
{
|
||||
int var = bdd_var(b);
|
||||
const bdd_dict::bdd_info& i = d->bdd_map[var];
|
||||
assert(i.type == bdd_dict::var);
|
||||
formula res = i.f;
|
||||
|
||||
bdd high = bdd_high(b);
|
||||
if (high == bddfalse)
|
||||
{
|
||||
res = formula::Not(res);
|
||||
b = bdd_low(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If bdd_low is not false, then b was not a conjunction.
|
||||
assert(bdd_low(b) == bddfalse);
|
||||
b = high;
|
||||
}
|
||||
assert(b != bddfalse);
|
||||
v.push_back(res);
|
||||
}
|
||||
bdd high = bdd_high(b);
|
||||
if (high == bddfalse)
|
||||
{
|
||||
res = formula::Not(res);
|
||||
b = bdd_low(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If bdd_low is not false, then b was not a conjunction.
|
||||
assert(bdd_low(b) == bddfalse);
|
||||
b = high;
|
||||
}
|
||||
assert(b != bddfalse);
|
||||
v.push_back(res);
|
||||
}
|
||||
return formula::And(v);
|
||||
}
|
||||
} // anonymous
|
||||
|
|
@ -66,14 +66,14 @@ namespace spot
|
|||
{
|
||||
auto recurse = [&d, owner](formula f)
|
||||
{
|
||||
return formula_to_bdd(f, d, owner);
|
||||
return formula_to_bdd(f, d, owner);
|
||||
};
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::ff:
|
||||
return bddfalse;
|
||||
return bddfalse;
|
||||
case op::tt:
|
||||
return bddtrue;
|
||||
return bddtrue;
|
||||
case op::eword:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
|
|
@ -95,32 +95,32 @@ namespace spot
|
|||
case op::AndNLM:
|
||||
case op::OrRat:
|
||||
case op::AndRat:
|
||||
SPOT_UNIMPLEMENTED();
|
||||
SPOT_UNIMPLEMENTED();
|
||||
case op::ap:
|
||||
return bdd_ithvar(d->register_proposition(f, owner));
|
||||
return bdd_ithvar(d->register_proposition(f, owner));
|
||||
case op::Not:
|
||||
return bdd_not(recurse(f[0]));
|
||||
return bdd_not(recurse(f[0]));
|
||||
case op::Xor:
|
||||
return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_xor);
|
||||
return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_xor);
|
||||
case op::Implies:
|
||||
return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_imp);
|
||||
return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_imp);
|
||||
case op::Equiv:
|
||||
return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_biimp);
|
||||
return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_biimp);
|
||||
case op::And:
|
||||
case op::Or:
|
||||
{
|
||||
int o = bddop_and;
|
||||
bdd res = bddtrue;
|
||||
if (f.is(op::Or))
|
||||
{
|
||||
o = bddop_or;
|
||||
res = bddfalse;
|
||||
}
|
||||
unsigned s = f.size();
|
||||
for (unsigned n = 0; n < s; ++n)
|
||||
res = bdd_apply(res, recurse(f[n]), o);
|
||||
return res;
|
||||
}
|
||||
{
|
||||
int o = bddop_and;
|
||||
bdd res = bddtrue;
|
||||
if (f.is(op::Or))
|
||||
{
|
||||
o = bddop_or;
|
||||
res = bddfalse;
|
||||
}
|
||||
unsigned s = f.size();
|
||||
for (unsigned n = 0; n < s; ++n)
|
||||
res = bdd_apply(res, recurse(f[n]), o);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
return bddfalse;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace spot
|
|||
template<typename T>
|
||||
SPOT_API bdd
|
||||
formula_to_bdd(formula f, const bdd_dict_ptr& d,
|
||||
const std::shared_ptr<T>& for_me)
|
||||
const std::shared_ptr<T>& for_me)
|
||||
{
|
||||
return formula_to_bdd(f, d, for_me.get());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ namespace spot
|
|||
{
|
||||
int i = *it1++ - *it2++;
|
||||
if (i != 0)
|
||||
return i;
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -162,14 +162,14 @@ namespace spot
|
|||
unsigned p;
|
||||
for (p = 0; p < pos.size() && t->condition != bddfalse; ++p)
|
||||
{
|
||||
taa_tgba::state_set::const_iterator j;
|
||||
for (j = (*pos[p])->dst->begin(); j != (*pos[p])->dst->end(); ++j)
|
||||
if ((*j)->size() > 0) // Remove sink states.
|
||||
ss->insert(*j);
|
||||
taa_tgba::state_set::const_iterator j;
|
||||
for (j = (*pos[p])->dst->begin(); j != (*pos[p])->dst->end(); ++j)
|
||||
if ((*j)->size() > 0) // Remove sink states.
|
||||
ss->insert(*j);
|
||||
|
||||
// Fill the new transition.
|
||||
t->condition &= (*pos[p])->condition;
|
||||
t->acceptance_conditions |= (*pos[p])->acceptance_conditions;
|
||||
// Fill the new transition.
|
||||
t->condition &= (*pos[p])->condition;
|
||||
t->acceptance_conditions |= (*pos[p])->acceptance_conditions;
|
||||
} // If p != pos.size() we have found a contradiction
|
||||
assert(p > 0);
|
||||
t->dst = ss;
|
||||
|
|
@ -182,54 +182,54 @@ namespace spot
|
|||
std::vector<taa_tgba::transition*>::iterator j;
|
||||
if (t->condition != bddfalse)
|
||||
{
|
||||
i = seen_.find(b);
|
||||
if (i != seen_.end())
|
||||
for (j = i->second.begin(); j != i->second.end(); ++j)
|
||||
{
|
||||
taa_tgba::transition* current = *j;
|
||||
if (*current->dst == *t->dst
|
||||
&& current->condition == t->condition)
|
||||
{
|
||||
current->acceptance_conditions &= t->acceptance_conditions;
|
||||
break;
|
||||
}
|
||||
if (*current->dst == *t->dst
|
||||
&& current->acceptance_conditions == t->acceptance_conditions)
|
||||
{
|
||||
current->condition |= t->condition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i = seen_.find(b);
|
||||
if (i != seen_.end())
|
||||
for (j = i->second.begin(); j != i->second.end(); ++j)
|
||||
{
|
||||
taa_tgba::transition* current = *j;
|
||||
if (*current->dst == *t->dst
|
||||
&& current->condition == t->condition)
|
||||
{
|
||||
current->acceptance_conditions &= t->acceptance_conditions;
|
||||
break;
|
||||
}
|
||||
if (*current->dst == *t->dst
|
||||
&& current->acceptance_conditions == t->acceptance_conditions)
|
||||
{
|
||||
current->condition |= t->condition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Mark the new transition as seen and keep it if we have not
|
||||
// found any contradiction and no other transition to merge
|
||||
// with, or delete it otherwise.
|
||||
if (t->condition != bddfalse
|
||||
&& (i == seen_.end() || j == i->second.end()))
|
||||
&& (i == seen_.end() || j == i->second.end()))
|
||||
{
|
||||
seen_[b].push_back(t);
|
||||
if (i != seen_.end())
|
||||
delete b;
|
||||
succ_.push_back(t);
|
||||
seen_[b].push_back(t);
|
||||
if (i != seen_.end())
|
||||
delete b;
|
||||
succ_.push_back(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete t->dst;
|
||||
delete t;
|
||||
delete b;
|
||||
delete t->dst;
|
||||
delete t;
|
||||
delete b;
|
||||
}
|
||||
|
||||
for (int i = pos.size() - 1; i >= 0; --i)
|
||||
{
|
||||
if ((i < int(p))
|
||||
&& (std::distance(pos[i], bounds[i].second) > 1
|
||||
|| (i == 0 && std::distance(pos[i], bounds[i].second) == 1)))
|
||||
{
|
||||
++pos[i];
|
||||
break;
|
||||
}
|
||||
else
|
||||
pos[i] = bounds[i].first;
|
||||
if ((i < int(p))
|
||||
&& (std::distance(pos[i], bounds[i].second) > 1
|
||||
|| (i == 0 && std::distance(pos[i], bounds[i].second) == 1)))
|
||||
{
|
||||
++pos[i];
|
||||
break;
|
||||
}
|
||||
else
|
||||
pos[i] = bounds[i].first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace spot
|
|||
virtual ~set_state()
|
||||
{
|
||||
if (delete_me_)
|
||||
delete s_;
|
||||
delete s_;
|
||||
}
|
||||
|
||||
const taa_tgba::state_set* get_state() const;
|
||||
|
|
@ -118,18 +118,18 @@ namespace spot
|
|||
typedef std::pair<iterator, iterator> iterator_pair;
|
||||
typedef std::vector<iterator_pair> bounds_t;
|
||||
typedef std::unordered_map<const spot::set_state*,
|
||||
std::vector<taa_tgba::transition*>,
|
||||
state_ptr_hash, state_ptr_equal> seen_map;
|
||||
std::vector<taa_tgba::transition*>,
|
||||
state_ptr_hash, state_ptr_equal> seen_map;
|
||||
|
||||
struct distance_sort :
|
||||
public std::binary_function<const iterator_pair&,
|
||||
const iterator_pair&, bool>
|
||||
const iterator_pair&, bool>
|
||||
{
|
||||
bool
|
||||
operator()(const iterator_pair& lhs, const iterator_pair& rhs) const
|
||||
{
|
||||
return std::distance(lhs.first, lhs.second) <
|
||||
std::distance(rhs.first, rhs.second);
|
||||
return std::distance(lhs.first, lhs.second) <
|
||||
std::distance(rhs.first, rhs.second);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -150,11 +150,11 @@ namespace spot
|
|||
~taa_tgba_labelled()
|
||||
{
|
||||
for (auto i: name_state_map_)
|
||||
{
|
||||
for (auto i2: *i.second)
|
||||
delete i2;
|
||||
delete i.second;
|
||||
}
|
||||
{
|
||||
for (auto i2: *i.second)
|
||||
delete i2;
|
||||
delete i.second;
|
||||
}
|
||||
}
|
||||
|
||||
void set_init_state(const label& s)
|
||||
|
|
@ -170,7 +170,7 @@ namespace spot
|
|||
|
||||
transition*
|
||||
create_transition(const label& s,
|
||||
const std::vector<label>& d)
|
||||
const std::vector<label>& d)
|
||||
{
|
||||
state* src = add_state(s);
|
||||
state_set* dst = add_state_set(d);
|
||||
|
|
@ -194,7 +194,7 @@ namespace spot
|
|||
{
|
||||
auto p = acc_map_.emplace(f, 0);
|
||||
if (p.second)
|
||||
p.first->second = acc_cond::mark_t({acc().add_set()});
|
||||
p.first->second = acc_cond::mark_t({acc().add_set()});
|
||||
t->acceptance_conditions |= p.first->second;
|
||||
}
|
||||
|
||||
|
|
@ -220,14 +220,14 @@ namespace spot
|
|||
typename ns_map::const_iterator i;
|
||||
for (i = name_state_map_.begin(); i != name_state_map_.end(); ++i)
|
||||
{
|
||||
taa_tgba::state::const_iterator i2;
|
||||
os << "State: " << label_to_string(i->first) << std::endl;
|
||||
for (i2 = i->second->begin(); i2 != i->second->end(); ++i2)
|
||||
{
|
||||
os << ' ' << format_state_set((*i2)->dst)
|
||||
<< ", C:" << (*i2)->condition
|
||||
<< ", A:" << (*i2)->acceptance_conditions << std::endl;
|
||||
}
|
||||
taa_tgba::state::const_iterator i2;
|
||||
os << "State: " << label_to_string(i->first) << std::endl;
|
||||
for (i2 = i->second->begin(); i2 != i->second->end(); ++i2)
|
||||
{
|
||||
os << ' ' << format_state_set((*i2)->dst)
|
||||
<< ", C:" << (*i2)->condition
|
||||
<< ", A:" << (*i2)->acceptance_conditions << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ namespace spot
|
|||
|
||||
typedef std::unordered_map<label, taa_tgba::state*> ns_map;
|
||||
typedef std::unordered_map<const taa_tgba::state*, label,
|
||||
ptr_hash<taa_tgba::state> > sn_map;
|
||||
ptr_hash<taa_tgba::state> > sn_map;
|
||||
|
||||
ns_map name_state_map_;
|
||||
sn_map state_name_map_;
|
||||
|
|
@ -252,10 +252,10 @@ namespace spot
|
|||
typename ns_map::iterator i = name_state_map_.find(name);
|
||||
if (i == name_state_map_.end())
|
||||
{
|
||||
taa_tgba::state* s = new taa_tgba::state;
|
||||
name_state_map_[name] = s;
|
||||
state_name_map_[s] = name;
|
||||
return s;
|
||||
taa_tgba::state* s = new taa_tgba::state;
|
||||
name_state_map_[name] = s;
|
||||
state_name_map_[s] = name;
|
||||
return s;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
|
@ -265,7 +265,7 @@ namespace spot
|
|||
{
|
||||
state_set* ss = new state_set;
|
||||
for (unsigned i = 0; i < names.size(); ++i)
|
||||
ss->insert(add_state(names[i]));
|
||||
ss->insert(add_state(names[i]));
|
||||
state_set_vec_.push_back(ss);
|
||||
return ss;
|
||||
}
|
||||
|
|
@ -275,25 +275,25 @@ namespace spot
|
|||
state_set::const_iterator i1 = ss->begin();
|
||||
typename sn_map::const_iterator i2;
|
||||
if (ss->empty())
|
||||
return std::string("{}");
|
||||
return std::string("{}");
|
||||
if (ss->size() == 1)
|
||||
{
|
||||
i2 = state_name_map_.find(*i1);
|
||||
assert(i2 != state_name_map_.end());
|
||||
return "{" + label_to_string(i2->second) + "}";
|
||||
i2 = state_name_map_.find(*i1);
|
||||
assert(i2 != state_name_map_.end());
|
||||
return "{" + label_to_string(i2->second) + "}";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string res("{");
|
||||
while (i1 != ss->end())
|
||||
{
|
||||
i2 = state_name_map_.find(*i1++);
|
||||
assert(i2 != state_name_map_.end());
|
||||
res += label_to_string(i2->second);
|
||||
res += ",";
|
||||
}
|
||||
res[res.size() - 1] = '}';
|
||||
return res;
|
||||
std::string res("{");
|
||||
while (i1 != ss->end())
|
||||
{
|
||||
i2 = state_name_map_.find(*i1++);
|
||||
assert(i2 != state_name_map_.end());
|
||||
res += label_to_string(i2->second);
|
||||
res += ",";
|
||||
}
|
||||
res[res.size() - 1] = '}';
|
||||
return res;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace spot
|
|||
|
||||
state*
|
||||
twa::project_state(const state* s,
|
||||
const const_twa_ptr& t) const
|
||||
const const_twa_ptr& t) const
|
||||
{
|
||||
if (t.get() == this)
|
||||
return s->clone();
|
||||
|
|
@ -61,25 +61,25 @@ namespace spot
|
|||
auto a = shared_from_this();
|
||||
if (a->acc().uses_fin_acceptance())
|
||||
{
|
||||
auto aa = std::dynamic_pointer_cast<const twa_graph>(a);
|
||||
if (!aa)
|
||||
aa = make_twa_graph(a, prop_set::all());
|
||||
a = remove_fin(aa);
|
||||
auto aa = std::dynamic_pointer_cast<const twa_graph>(a);
|
||||
if (!aa)
|
||||
aa = make_twa_graph(a, prop_set::all());
|
||||
a = remove_fin(aa);
|
||||
}
|
||||
return !couvreur99(a)->check();
|
||||
}
|
||||
|
||||
void
|
||||
twa::set_named_prop(std::string s,
|
||||
void* val, std::function<void(void*)> destructor)
|
||||
void* val, std::function<void(void*)> destructor)
|
||||
{
|
||||
auto p = named_prop_.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(s),
|
||||
std::forward_as_tuple(val, destructor));
|
||||
std::forward_as_tuple(s),
|
||||
std::forward_as_tuple(val, destructor));
|
||||
if (!p.second)
|
||||
{
|
||||
p.first->second.second(p.first->second.first);
|
||||
p.first->second = std::make_pair(val, destructor);
|
||||
p.first->second.second(p.first->second.first);
|
||||
p.first->second = std::make_pair(val, destructor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
170
spot/twa/twa.hh
170
spot/twa/twa.hh
|
|
@ -180,14 +180,14 @@ namespace spot
|
|||
///
|
||||
/// \see state_unicity_table
|
||||
typedef std::unordered_set<const state*,
|
||||
state_ptr_hash, state_ptr_equal> state_set;
|
||||
state_ptr_hash, state_ptr_equal> state_set;
|
||||
|
||||
/// \brief Unordered map of abstract states
|
||||
///
|
||||
/// Destroying each state if needed is the user's responsibility.
|
||||
template<class val>
|
||||
using state_map = std::unordered_map<const state*, val,
|
||||
state_ptr_hash, state_ptr_equal>;
|
||||
state_ptr_hash, state_ptr_equal>;
|
||||
|
||||
/// \ingroup twa_essentials
|
||||
/// \brief Render state pointers unique via a hash table.
|
||||
|
|
@ -208,7 +208,7 @@ namespace spot
|
|||
{
|
||||
auto p = m.insert(s);
|
||||
if (!p.second)
|
||||
s->destroy();
|
||||
s->destroy();
|
||||
return *p.first;
|
||||
}
|
||||
|
||||
|
|
@ -220,22 +220,22 @@ namespace spot
|
|||
{
|
||||
auto p = m.insert(s);
|
||||
if (!p.second)
|
||||
{
|
||||
s->destroy();
|
||||
return nullptr;
|
||||
}
|
||||
{
|
||||
s->destroy();
|
||||
return nullptr;
|
||||
}
|
||||
return *p.first;
|
||||
}
|
||||
|
||||
~state_unicity_table()
|
||||
{
|
||||
for (state_set::iterator i = m.begin(); i != m.end();)
|
||||
{
|
||||
// Advance the iterator before destroying its key. This
|
||||
// avoid issues with old g++ implementations.
|
||||
state_set::iterator old = i++;
|
||||
(*old)->destroy();
|
||||
}
|
||||
{
|
||||
// Advance the iterator before destroying its key. This
|
||||
// avoid issues with old g++ implementations.
|
||||
state_set::iterator old = i++;
|
||||
(*old)->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
|
|
@ -336,8 +336,8 @@ namespace spot
|
|||
|
||||
/// Unordered set of shared states
|
||||
typedef std::unordered_set<shared_state,
|
||||
state_shared_ptr_hash,
|
||||
state_shared_ptr_equal> shared_state_set;
|
||||
state_shared_ptr_hash,
|
||||
state_shared_ptr_equal> shared_state_set;
|
||||
|
||||
/// \ingroup twa_essentials
|
||||
/// \brief Iterate over the successors of a state.
|
||||
|
|
@ -483,29 +483,29 @@ namespace spot
|
|||
public:
|
||||
|
||||
succ_iterator(twa_succ_iterator* it):
|
||||
it_(it)
|
||||
it_(it)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(succ_iterator o) const
|
||||
{
|
||||
return it_ == o.it_;
|
||||
return it_ == o.it_;
|
||||
}
|
||||
|
||||
bool operator!=(succ_iterator o) const
|
||||
{
|
||||
return it_ != o.it_;
|
||||
return it_ != o.it_;
|
||||
}
|
||||
|
||||
const twa_succ_iterator* operator*() const
|
||||
{
|
||||
return it_;
|
||||
return it_;
|
||||
}
|
||||
|
||||
void operator++()
|
||||
{
|
||||
if (!it_->next())
|
||||
it_ = nullptr;
|
||||
if (!it_->next())
|
||||
it_ = nullptr;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -597,30 +597,30 @@ namespace spot
|
|||
twa_succ_iterator* it_;
|
||||
public:
|
||||
succ_iterable(const twa* aut, twa_succ_iterator* it)
|
||||
: aut_(aut), it_(it)
|
||||
: aut_(aut), it_(it)
|
||||
{
|
||||
}
|
||||
|
||||
succ_iterable(succ_iterable&& other)
|
||||
: aut_(other.aut_), it_(other.it_)
|
||||
: aut_(other.aut_), it_(other.it_)
|
||||
{
|
||||
other.it_ = nullptr;
|
||||
other.it_ = nullptr;
|
||||
}
|
||||
|
||||
~succ_iterable()
|
||||
{
|
||||
if (it_)
|
||||
aut_->release_iter(it_);
|
||||
if (it_)
|
||||
aut_->release_iter(it_);
|
||||
}
|
||||
|
||||
internal::succ_iterator begin()
|
||||
{
|
||||
return it_->first() ? it_ : nullptr;
|
||||
return it_->first() ? it_ : nullptr;
|
||||
}
|
||||
|
||||
internal::succ_iterator end()
|
||||
{
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
|
@ -682,9 +682,9 @@ namespace spot
|
|||
void release_iter(twa_succ_iterator* i) const
|
||||
{
|
||||
if (iter_cache_)
|
||||
delete i;
|
||||
delete i;
|
||||
else
|
||||
iter_cache_ = i;
|
||||
iter_cache_ = i;
|
||||
}
|
||||
|
||||
/// \brief Get the dictionary associated to the automaton.
|
||||
|
|
@ -724,11 +724,11 @@ namespace spot
|
|||
{
|
||||
int res = dict_->has_registered_proposition(ap, this);
|
||||
if (res < 0)
|
||||
{
|
||||
aps_.push_back(ap);
|
||||
res = dict_->register_proposition(ap, this);
|
||||
bddaps_ &= bdd_ithvar(res);
|
||||
}
|
||||
{
|
||||
aps_.push_back(ap);
|
||||
res = dict_->register_proposition(ap, this);
|
||||
bddaps_ &= bdd_ithvar(res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -773,7 +773,7 @@ namespace spot
|
|||
/// or a new \c state* (the projected state) that must be
|
||||
/// destroyed by the caller.
|
||||
virtual state* project_state(const state* s,
|
||||
const const_twa_ptr& t) const;
|
||||
const const_twa_ptr& t) const;
|
||||
|
||||
///@{
|
||||
/// \brief The acceptance condition of the automaton.
|
||||
|
|
@ -797,10 +797,10 @@ namespace spot
|
|||
void set_num_sets_(unsigned num)
|
||||
{
|
||||
if (num < acc_.num_sets())
|
||||
{
|
||||
acc_.~acc_cond();
|
||||
new (&acc_) acc_cond;
|
||||
}
|
||||
{
|
||||
acc_.~acc_cond();
|
||||
new (&acc_) acc_cond;
|
||||
}
|
||||
acc_.add_sets(num - acc_.num_sets());
|
||||
}
|
||||
|
||||
|
|
@ -826,7 +826,7 @@ namespace spot
|
|||
set_num_sets_(num);
|
||||
acc_.set_acceptance(c);
|
||||
if (num == 0)
|
||||
prop_state_acc(true);
|
||||
prop_state_acc(true);
|
||||
}
|
||||
|
||||
/// Copy the acceptance condition of another TωA.
|
||||
|
|
@ -835,14 +835,14 @@ namespace spot
|
|||
acc_ = a->acc();
|
||||
unsigned num = acc_.num_sets();
|
||||
if (num == 0)
|
||||
prop_state_acc(true);
|
||||
prop_state_acc(true);
|
||||
}
|
||||
|
||||
/// Copy the atomic propositions of another TωA
|
||||
void copy_ap_of(const const_twa_ptr& a)
|
||||
{
|
||||
for (auto f: a->ap())
|
||||
this->register_ap(f);
|
||||
this->register_ap(f);
|
||||
}
|
||||
|
||||
/// \brief Set generalized Büchi acceptance
|
||||
|
|
@ -862,7 +862,7 @@ namespace spot
|
|||
set_num_sets_(num);
|
||||
acc_.set_generalized_buchi();
|
||||
if (num == 0)
|
||||
prop_state_acc(true);
|
||||
prop_state_acc(true);
|
||||
}
|
||||
|
||||
/// \brief Set Büchi acceptance.
|
||||
|
|
@ -895,8 +895,8 @@ namespace spot
|
|||
{
|
||||
trival::repr_t state_based_acc:2; // State-based acceptance.
|
||||
trival::repr_t inherently_weak:2; // Inherently Weak automaton.
|
||||
trival::repr_t weak:2; // Weak automaton.
|
||||
trival::repr_t terminal:2; // Terminal automaton.
|
||||
trival::repr_t weak:2; // Weak automaton.
|
||||
trival::repr_t terminal:2; // Terminal automaton.
|
||||
trival::repr_t deterministic:2; // Deterministic automaton.
|
||||
trival::repr_t unambiguous:2; // Unambiguous automaton.
|
||||
trival::repr_t stutter_invariant:2; // Stutter invariant language.
|
||||
|
|
@ -910,8 +910,8 @@ namespace spot
|
|||
#ifndef SWIG
|
||||
// Dynamic properties, are given with a name and a destructor function.
|
||||
std::unordered_map<std::string,
|
||||
std::pair<void*,
|
||||
std::function<void(void*)>>> named_prop_;
|
||||
std::pair<void*,
|
||||
std::function<void(void*)>>> named_prop_;
|
||||
#endif
|
||||
void* get_named_prop_(std::string s) const;
|
||||
|
||||
|
|
@ -930,7 +930,7 @@ namespace spot
|
|||
/// When the automaton is destroyed, the \a destructor function will
|
||||
/// be called to destroy the attached object.
|
||||
void set_named_prop(std::string s,
|
||||
void* val, std::function<void(void*)> destructor);
|
||||
void* val, std::function<void(void*)> destructor);
|
||||
|
||||
/// \brief Declare a named property
|
||||
///
|
||||
|
|
@ -966,7 +966,7 @@ namespace spot
|
|||
{
|
||||
void* p = get_named_prop_(s);
|
||||
if (!p)
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -979,7 +979,7 @@ namespace spot
|
|||
{
|
||||
// Destroy all named properties.
|
||||
for (auto& np: named_prop_)
|
||||
np.second.second(np.second.first);
|
||||
np.second.second(np.second.first);
|
||||
named_prop_.clear();
|
||||
}
|
||||
|
||||
|
|
@ -1036,7 +1036,7 @@ namespace spot
|
|||
{
|
||||
is.inherently_weak = val.val();
|
||||
if (!val)
|
||||
is.terminal = is.weak = val.val();
|
||||
is.terminal = is.weak = val.val();
|
||||
}
|
||||
|
||||
/// \brief Whether the automaton is terminal.
|
||||
|
|
@ -1064,7 +1064,7 @@ namespace spot
|
|||
{
|
||||
is.terminal = val.val();
|
||||
if (val)
|
||||
is.inherently_weak = is.weak = val.val();
|
||||
is.inherently_weak = is.weak = val.val();
|
||||
}
|
||||
|
||||
/// \brief Whether the automaton is weak.
|
||||
|
|
@ -1091,9 +1091,9 @@ namespace spot
|
|||
{
|
||||
is.weak = val.val();
|
||||
if (val)
|
||||
is.inherently_weak = val.val();
|
||||
is.inherently_weak = val.val();
|
||||
if (!val)
|
||||
is.terminal = val.val();
|
||||
is.terminal = val.val();
|
||||
}
|
||||
|
||||
/// \brief Whether the automaton is deterministic.
|
||||
|
|
@ -1122,8 +1122,8 @@ namespace spot
|
|||
{
|
||||
is.deterministic = val.val();
|
||||
if (val)
|
||||
// deterministic implies unambiguous
|
||||
is.unambiguous = val.val();
|
||||
// deterministic implies unambiguous
|
||||
is.unambiguous = val.val();
|
||||
}
|
||||
|
||||
/// \brief Whether the automaton is unambiguous
|
||||
|
|
@ -1154,7 +1154,7 @@ namespace spot
|
|||
{
|
||||
is.unambiguous = val.val();
|
||||
if (!val)
|
||||
is.deterministic = val.val();
|
||||
is.deterministic = val.val();
|
||||
}
|
||||
|
||||
/// \brief Whether the automaton is stutter-invariant.
|
||||
|
|
@ -1215,10 +1215,10 @@ namespace spot
|
|||
/// \see prop_copy
|
||||
struct prop_set
|
||||
{
|
||||
bool state_based; ///< preserve state-based acceptnace
|
||||
bool inherently_weak; ///< preserve inherently weak, weak, & terminal
|
||||
bool deterministic; ///< preserve deterministic and unambiguous
|
||||
bool stutter_inv; ///< preserve stutter invariance
|
||||
bool state_based; ///< preserve state-based acceptnace
|
||||
bool inherently_weak; ///< preserve inherently weak, weak, & terminal
|
||||
bool deterministic; ///< preserve deterministic and unambiguous
|
||||
bool stutter_inv; ///< preserve stutter invariance
|
||||
|
||||
/// \brief An all-true \c prop_set
|
||||
///
|
||||
|
|
@ -1237,7 +1237,7 @@ namespace spot
|
|||
/// algorithm X, in case that new property is not preserved.
|
||||
static prop_set all()
|
||||
{
|
||||
return { true, true, true, true };
|
||||
return { true, true, true, true };
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1254,20 +1254,20 @@ namespace spot
|
|||
void prop_copy(const const_twa_ptr& other, prop_set p)
|
||||
{
|
||||
if (p.state_based)
|
||||
prop_state_acc(other->prop_state_acc());
|
||||
prop_state_acc(other->prop_state_acc());
|
||||
if (p.inherently_weak)
|
||||
{
|
||||
prop_terminal(other->prop_terminal());
|
||||
prop_weak(other->prop_weak());
|
||||
prop_inherently_weak(other->prop_inherently_weak());
|
||||
}
|
||||
{
|
||||
prop_terminal(other->prop_terminal());
|
||||
prop_weak(other->prop_weak());
|
||||
prop_inherently_weak(other->prop_inherently_weak());
|
||||
}
|
||||
if (p.deterministic)
|
||||
{
|
||||
prop_deterministic(other->prop_deterministic());
|
||||
prop_unambiguous(other->prop_unambiguous());
|
||||
}
|
||||
{
|
||||
prop_deterministic(other->prop_deterministic());
|
||||
prop_unambiguous(other->prop_unambiguous());
|
||||
}
|
||||
if (p.stutter_inv)
|
||||
prop_stutter_invariant(other->prop_stutter_invariant());
|
||||
prop_stutter_invariant(other->prop_stutter_invariant());
|
||||
}
|
||||
|
||||
/// \brief Keep only a subset of properties of the current
|
||||
|
|
@ -1278,20 +1278,20 @@ namespace spot
|
|||
void prop_keep(prop_set p)
|
||||
{
|
||||
if (!p.state_based)
|
||||
prop_state_acc(trival::maybe());
|
||||
prop_state_acc(trival::maybe());
|
||||
if (!p.inherently_weak)
|
||||
{
|
||||
prop_terminal(trival::maybe());
|
||||
prop_weak(trival::maybe());
|
||||
prop_inherently_weak(trival::maybe());
|
||||
}
|
||||
{
|
||||
prop_terminal(trival::maybe());
|
||||
prop_weak(trival::maybe());
|
||||
prop_inherently_weak(trival::maybe());
|
||||
}
|
||||
if (!p.deterministic)
|
||||
{
|
||||
prop_deterministic(trival::maybe());
|
||||
prop_unambiguous(trival::maybe());
|
||||
}
|
||||
{
|
||||
prop_deterministic(trival::maybe());
|
||||
prop_unambiguous(trival::maybe());
|
||||
}
|
||||
if (!p.stutter_inv)
|
||||
prop_stutter_invariant(trival::maybe());
|
||||
prop_stutter_invariant(trival::maybe());
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,21 +24,21 @@ namespace spot
|
|||
{
|
||||
void
|
||||
twa_graph::release_formula_namer(namer<formula>* namer,
|
||||
bool keep_names)
|
||||
bool keep_names)
|
||||
{
|
||||
if (keep_names)
|
||||
{
|
||||
auto v = new std::vector<std::string>(num_states());
|
||||
auto& n = namer->names();
|
||||
unsigned ns = n.size();
|
||||
assert(n.size() <= v->size());
|
||||
for (unsigned i = 0; i < ns; ++i)
|
||||
{
|
||||
auto f = n[i];
|
||||
if (f)
|
||||
(*v)[i] = str_psl(f);
|
||||
}
|
||||
set_named_prop("state-names", v);
|
||||
auto v = new std::vector<std::string>(num_states());
|
||||
auto& n = namer->names();
|
||||
unsigned ns = n.size();
|
||||
assert(n.size() <= v->size());
|
||||
for (unsigned i = 0; i < ns; ++i)
|
||||
{
|
||||
auto f = n[i];
|
||||
if (f)
|
||||
(*v)[i] = str_psl(f);
|
||||
}
|
||||
set_named_prop("state-names", v);
|
||||
}
|
||||
delete namer;
|
||||
}
|
||||
|
|
@ -49,19 +49,19 @@ namespace spot
|
|||
|
||||
typedef graph_t::edge_storage_t tr_t;
|
||||
g_.sort_edges_([](const tr_t& lhs, const tr_t& rhs)
|
||||
{
|
||||
if (lhs.src < rhs.src)
|
||||
return true;
|
||||
if (lhs.src > rhs.src)
|
||||
return false;
|
||||
if (lhs.dst < rhs.dst)
|
||||
return true;
|
||||
if (lhs.dst > rhs.dst)
|
||||
return false;
|
||||
return lhs.acc < rhs.acc;
|
||||
// Do not sort on conditions, we'll merge
|
||||
// them.
|
||||
});
|
||||
{
|
||||
if (lhs.src < rhs.src)
|
||||
return true;
|
||||
if (lhs.src > rhs.src)
|
||||
return false;
|
||||
if (lhs.dst < rhs.dst)
|
||||
return true;
|
||||
if (lhs.dst > rhs.dst)
|
||||
return false;
|
||||
return lhs.acc < rhs.acc;
|
||||
// Do not sort on conditions, we'll merge
|
||||
// them.
|
||||
});
|
||||
|
||||
auto& trans = this->edge_vector();
|
||||
unsigned tend = trans.size();
|
||||
|
|
@ -72,30 +72,30 @@ namespace spot
|
|||
++in;
|
||||
if (in < tend)
|
||||
{
|
||||
++out;
|
||||
if (out != in)
|
||||
trans[out] = trans[in];
|
||||
for (++in; in < tend; ++in)
|
||||
{
|
||||
if (trans[in].cond == bddfalse) // Unusable edge
|
||||
continue;
|
||||
// Merge edges with the same source, destination, and
|
||||
// acceptance. (We test the source last, because this is the
|
||||
// most likely test to be true as edges are ordered by
|
||||
// sources and then destinations.)
|
||||
if (trans[out].dst == trans[in].dst
|
||||
&& trans[out].acc == trans[in].acc
|
||||
&& trans[out].src == trans[in].src)
|
||||
{
|
||||
trans[out].cond |= trans[in].cond;
|
||||
}
|
||||
else
|
||||
{
|
||||
++out;
|
||||
if (in != out)
|
||||
trans[out] = trans[in];
|
||||
}
|
||||
}
|
||||
++out;
|
||||
if (out != in)
|
||||
trans[out] = trans[in];
|
||||
for (++in; in < tend; ++in)
|
||||
{
|
||||
if (trans[in].cond == bddfalse) // Unusable edge
|
||||
continue;
|
||||
// Merge edges with the same source, destination, and
|
||||
// acceptance. (We test the source last, because this is the
|
||||
// most likely test to be true as edges are ordered by
|
||||
// sources and then destinations.)
|
||||
if (trans[out].dst == trans[in].dst
|
||||
&& trans[out].acc == trans[in].acc
|
||||
&& trans[out].src == trans[in].src)
|
||||
{
|
||||
trans[out].cond |= trans[in].cond;
|
||||
}
|
||||
else
|
||||
{
|
||||
++out;
|
||||
if (in != out)
|
||||
trans[out] = trans[in];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (++out != tend)
|
||||
trans.resize(out);
|
||||
|
|
@ -109,42 +109,42 @@ namespace spot
|
|||
// both as Inf and Fin)
|
||||
if ((in < tend) && !acc().uses_fin_acceptance())
|
||||
{
|
||||
typedef graph_t::edge_storage_t tr_t;
|
||||
g_.sort_edges_([](const tr_t& lhs, const tr_t& rhs)
|
||||
{
|
||||
if (lhs.src < rhs.src)
|
||||
return true;
|
||||
if (lhs.src > rhs.src)
|
||||
return false;
|
||||
if (lhs.dst < rhs.dst)
|
||||
return true;
|
||||
if (lhs.dst > rhs.dst)
|
||||
return false;
|
||||
return lhs.cond.id() < rhs.cond.id();
|
||||
// Do not sort on acceptance, we'll merge
|
||||
// them.
|
||||
});
|
||||
typedef graph_t::edge_storage_t tr_t;
|
||||
g_.sort_edges_([](const tr_t& lhs, const tr_t& rhs)
|
||||
{
|
||||
if (lhs.src < rhs.src)
|
||||
return true;
|
||||
if (lhs.src > rhs.src)
|
||||
return false;
|
||||
if (lhs.dst < rhs.dst)
|
||||
return true;
|
||||
if (lhs.dst > rhs.dst)
|
||||
return false;
|
||||
return lhs.cond.id() < rhs.cond.id();
|
||||
// Do not sort on acceptance, we'll merge
|
||||
// them.
|
||||
});
|
||||
|
||||
for (; in < tend; ++in)
|
||||
{
|
||||
// Merge edges with the same source, destination,
|
||||
// and conditions. (We test the source last, for the
|
||||
// same reason as above.)
|
||||
if (trans[out].dst == trans[in].dst
|
||||
&& trans[out].cond.id() == trans[in].cond.id()
|
||||
&& trans[out].src == trans[in].src)
|
||||
{
|
||||
trans[out].acc |= trans[in].acc;
|
||||
}
|
||||
else
|
||||
{
|
||||
++out;
|
||||
if (in != out)
|
||||
trans[out] = trans[in];
|
||||
}
|
||||
}
|
||||
if (++out != tend)
|
||||
trans.resize(out);
|
||||
for (; in < tend; ++in)
|
||||
{
|
||||
// Merge edges with the same source, destination,
|
||||
// and conditions. (We test the source last, for the
|
||||
// same reason as above.)
|
||||
if (trans[out].dst == trans[in].dst
|
||||
&& trans[out].cond.id() == trans[in].cond.id()
|
||||
&& trans[out].src == trans[in].src)
|
||||
{
|
||||
trans[out].acc |= trans[in].acc;
|
||||
}
|
||||
else
|
||||
{
|
||||
++out;
|
||||
if (in != out)
|
||||
trans[out] = trans[in];
|
||||
}
|
||||
}
|
||||
if (++out != tend)
|
||||
trans.resize(out);
|
||||
}
|
||||
|
||||
g_.chain_edges_();
|
||||
|
|
@ -170,25 +170,25 @@ namespace spot
|
|||
unsigned todo_pos = 1;
|
||||
do
|
||||
{
|
||||
unsigned cur = todo[--todo_pos] & mask;
|
||||
todo[todo_pos] ^= cur; // Zero the state
|
||||
for (auto& t: g_.out(cur))
|
||||
if (!(todo[t.dst] & seen))
|
||||
{
|
||||
todo[t.dst] |= seen;
|
||||
todo[todo_pos++] |= t.dst;
|
||||
}
|
||||
unsigned cur = todo[--todo_pos] & mask;
|
||||
todo[todo_pos] ^= cur; // Zero the state
|
||||
for (auto& t: g_.out(cur))
|
||||
if (!(todo[t.dst] & seen))
|
||||
{
|
||||
todo[t.dst] |= seen;
|
||||
todo[todo_pos++] |= t.dst;
|
||||
}
|
||||
}
|
||||
while (todo_pos > 0);
|
||||
// Now renumber each used state.
|
||||
unsigned current = 0;
|
||||
for (auto& v: todo)
|
||||
if (!(v & seen))
|
||||
v = -1U;
|
||||
v = -1U;
|
||||
else
|
||||
v = current++;
|
||||
v = current++;
|
||||
if (current == todo.size())
|
||||
return; // No unreachable state.
|
||||
return; // No unreachable state.
|
||||
init_number_ = todo[init_number_];
|
||||
defrag_states(std::move(todo), current);
|
||||
}
|
||||
|
|
@ -209,46 +209,46 @@ namespace spot
|
|||
todo.emplace_back(init_number_, g_.state_storage(init_number_).succ);
|
||||
do
|
||||
{
|
||||
unsigned src;
|
||||
unsigned tid;
|
||||
std::tie(src, tid) = todo.back();
|
||||
if (tid == 0U)
|
||||
{
|
||||
todo.pop_back();
|
||||
order.push_back(src);
|
||||
continue;
|
||||
}
|
||||
auto& t = g_.edge_storage(tid);
|
||||
todo.back().second = t.next_succ;
|
||||
unsigned dst = t.dst;
|
||||
if (useful[dst] != 1)
|
||||
{
|
||||
todo.emplace_back(dst, g_.state_storage(dst).succ);
|
||||
useful[dst] = 1;
|
||||
}
|
||||
unsigned src;
|
||||
unsigned tid;
|
||||
std::tie(src, tid) = todo.back();
|
||||
if (tid == 0U)
|
||||
{
|
||||
todo.pop_back();
|
||||
order.push_back(src);
|
||||
continue;
|
||||
}
|
||||
auto& t = g_.edge_storage(tid);
|
||||
todo.back().second = t.next_succ;
|
||||
unsigned dst = t.dst;
|
||||
if (useful[dst] != 1)
|
||||
{
|
||||
todo.emplace_back(dst, g_.state_storage(dst).succ);
|
||||
useful[dst] = 1;
|
||||
}
|
||||
}
|
||||
while (!todo.empty());
|
||||
|
||||
// Process states in topological order
|
||||
for (auto s: order)
|
||||
{
|
||||
auto t = g_.out_iteraser(s);
|
||||
bool useless = true;
|
||||
while (t)
|
||||
{
|
||||
// Erase any edge to a useless state.
|
||||
if (!useful[t->dst])
|
||||
{
|
||||
t.erase();
|
||||
continue;
|
||||
}
|
||||
// if we have a edge to a useful state, then the
|
||||
// state is useful.
|
||||
useless = false;
|
||||
++t;
|
||||
}
|
||||
if (useless)
|
||||
useful[s] = 0;
|
||||
auto t = g_.out_iteraser(s);
|
||||
bool useless = true;
|
||||
while (t)
|
||||
{
|
||||
// Erase any edge to a useless state.
|
||||
if (!useful[t->dst])
|
||||
{
|
||||
t.erase();
|
||||
continue;
|
||||
}
|
||||
// if we have a edge to a useful state, then the
|
||||
// state is useful.
|
||||
useless = false;
|
||||
++t;
|
||||
}
|
||||
if (useless)
|
||||
useful[s] = 0;
|
||||
}
|
||||
|
||||
// Make sure the initial state is useful (even if it has been
|
||||
|
|
@ -260,30 +260,30 @@ namespace spot
|
|||
unsigned current = 0;
|
||||
for (unsigned s = 0; s < num_states; ++s)
|
||||
if (useful[s])
|
||||
useful[s] = current++;
|
||||
useful[s] = current++;
|
||||
else
|
||||
useful[s] = -1U;
|
||||
useful[s] = -1U;
|
||||
if (current == num_states)
|
||||
return; // No useless state.
|
||||
return; // No useless state.
|
||||
init_number_ = useful[init_number_];
|
||||
defrag_states(std::move(useful), current);
|
||||
}
|
||||
|
||||
void twa_graph::defrag_states(std::vector<unsigned>&& newst,
|
||||
unsigned used_states)
|
||||
unsigned used_states)
|
||||
{
|
||||
auto* names = get_named_prop<std::vector<std::string>>("state-names");
|
||||
if (names)
|
||||
{
|
||||
unsigned size = names->size();
|
||||
for (unsigned s = 0; s < size; ++s)
|
||||
{
|
||||
unsigned dst = newst[s];
|
||||
if (dst == s || dst == -1U)
|
||||
continue;
|
||||
(*names)[dst] = std::move((*names)[s]);
|
||||
}
|
||||
names->resize(used_states);
|
||||
unsigned size = names->size();
|
||||
for (unsigned s = 0; s < size; ++s)
|
||||
{
|
||||
unsigned dst = newst[s];
|
||||
if (dst == s || dst == -1U)
|
||||
continue;
|
||||
(*names)[dst] = std::move((*names)[s]);
|
||||
}
|
||||
names->resize(used_states);
|
||||
}
|
||||
g_.defrag_states(std::move(newst), used_states);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,16 +49,16 @@ namespace spot
|
|||
|
||||
// Do not simply return "other - this", it might not fit in an int.
|
||||
if (o < this)
|
||||
return -1;
|
||||
return -1;
|
||||
if (o > this)
|
||||
return 1;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t hash() const override
|
||||
{
|
||||
return
|
||||
reinterpret_cast<const char*>(this) - static_cast<const char*>(nullptr);
|
||||
reinterpret_cast<const char*>(this) - static_cast<const char*>(nullptr);
|
||||
}
|
||||
|
||||
virtual twa_graph_state*
|
||||
|
|
@ -90,9 +90,9 @@ namespace spot
|
|||
bool operator<(const twa_graph_edge_data& other) const
|
||||
{
|
||||
if (cond.id() < other.cond.id())
|
||||
return true;
|
||||
return true;
|
||||
if (cond.id() > other.cond.id())
|
||||
return false;
|
||||
return false;
|
||||
return acc < other.acc;
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ namespace spot
|
|||
// handle graph_t::state as an abstract type.
|
||||
typedef unsigned state_num;
|
||||
static_assert(std::is_same<typename graph_t::state, state_num>::value,
|
||||
"type mismatch");
|
||||
"type mismatch");
|
||||
|
||||
protected:
|
||||
graph_t g_;
|
||||
|
|
@ -187,7 +187,7 @@ namespace spot
|
|||
public:
|
||||
twa_graph(const bdd_dict_ptr& dict)
|
||||
: twa(dict),
|
||||
init_number_(0)
|
||||
init_number_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -195,9 +195,9 @@ namespace spot
|
|||
: twa(other->get_dict()),
|
||||
g_(other->g_), init_number_(other->init_number_)
|
||||
{
|
||||
copy_acceptance_of(other);
|
||||
copy_ap_of(other);
|
||||
prop_copy(other, p);
|
||||
copy_acceptance_of(other);
|
||||
copy_ap_of(other);
|
||||
prop_copy(other, p);
|
||||
}
|
||||
|
||||
virtual ~twa_graph()
|
||||
|
|
@ -206,13 +206,13 @@ namespace spot
|
|||
|
||||
#ifndef SWIG
|
||||
template <typename State_Name,
|
||||
typename Name_Hash = std::hash<State_Name>,
|
||||
typename Name_Equal = std::equal_to<State_Name>>
|
||||
typename Name_Hash = std::hash<State_Name>,
|
||||
typename Name_Equal = std::equal_to<State_Name>>
|
||||
using namer = named_graph<graph_t, State_Name, Name_Hash, Name_Equal>;
|
||||
|
||||
template <typename State_Name,
|
||||
typename Name_Hash = std::hash<State_Name>,
|
||||
typename Name_Equal = std::equal_to<State_Name>>
|
||||
typename Name_Hash = std::hash<State_Name>,
|
||||
typename Name_Equal = std::equal_to<State_Name>>
|
||||
namer<State_Name, Name_Hash, Name_Equal>*
|
||||
create_namer()
|
||||
{
|
||||
|
|
@ -263,14 +263,14 @@ namespace spot
|
|||
state_num get_init_state_number() const
|
||||
{
|
||||
if (num_states() == 0)
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
return init_number_;
|
||||
}
|
||||
|
||||
virtual const twa_graph_state* get_init_state() const override
|
||||
{
|
||||
if (num_states() == 0)
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
return state_from_number(init_number_);
|
||||
}
|
||||
|
||||
|
|
@ -282,13 +282,13 @@ namespace spot
|
|||
assert(!s->succ || g_.valid_trans(s->succ));
|
||||
|
||||
if (this->iter_cache_)
|
||||
{
|
||||
auto it =
|
||||
down_cast<twa_graph_succ_iterator<graph_t>*>(this->iter_cache_);
|
||||
it->recycle(s->succ);
|
||||
this->iter_cache_ = nullptr;
|
||||
return it;
|
||||
}
|
||||
{
|
||||
auto it =
|
||||
down_cast<twa_graph_succ_iterator<graph_t>*>(this->iter_cache_);
|
||||
it->recycle(s->succ);
|
||||
this->iter_cache_ = nullptr;
|
||||
return it;
|
||||
}
|
||||
return new twa_graph_succ_iterator<graph_t>(&g_, s->succ);
|
||||
}
|
||||
|
||||
|
|
@ -374,18 +374,18 @@ namespace spot
|
|||
}
|
||||
|
||||
unsigned new_edge(unsigned src, unsigned dst,
|
||||
bdd cond, acc_cond::mark_t acc = 0U)
|
||||
bdd cond, acc_cond::mark_t acc = 0U)
|
||||
{
|
||||
return g_.new_edge(src, dst, cond, acc);
|
||||
}
|
||||
|
||||
unsigned new_acc_edge(unsigned src, unsigned dst,
|
||||
bdd cond, bool acc = true)
|
||||
bdd cond, bool acc = true)
|
||||
{
|
||||
if (acc)
|
||||
return g_.new_edge(src, dst, cond, this->acc().all_sets());
|
||||
return g_.new_edge(src, dst, cond, this->acc().all_sets());
|
||||
else
|
||||
return g_.new_edge(src, dst, cond);
|
||||
return g_.new_edge(src, dst, cond);
|
||||
}
|
||||
|
||||
#ifndef SWIG
|
||||
|
|
@ -445,9 +445,9 @@ namespace spot
|
|||
{
|
||||
assert((bool)prop_state_acc() || num_sets() == 0);
|
||||
for (auto& t: g_.out(s))
|
||||
// Stop at the first edge, since the remaining should be
|
||||
// labeled identically.
|
||||
return t.acc;
|
||||
// Stop at the first edge, since the remaining should be
|
||||
// labeled identically.
|
||||
return t.acc;
|
||||
return 0U;
|
||||
}
|
||||
|
||||
|
|
@ -455,9 +455,9 @@ namespace spot
|
|||
{
|
||||
assert((bool)prop_state_acc() || num_sets() == 0);
|
||||
for (auto& t: g_.out(s))
|
||||
// Stop at the first edge, since the remaining should be
|
||||
// labeled identically.
|
||||
return acc().accepting(t.acc);
|
||||
// Stop at the first edge, since the remaining should be
|
||||
// labeled identically.
|
||||
return acc().accepting(t.acc);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -487,19 +487,19 @@ namespace spot
|
|||
}
|
||||
|
||||
inline twa_graph_ptr make_twa_graph(const twa_graph_ptr& aut,
|
||||
twa::prop_set p)
|
||||
twa::prop_set p)
|
||||
{
|
||||
return std::make_shared<twa_graph>(aut, p);
|
||||
}
|
||||
|
||||
inline twa_graph_ptr make_twa_graph(const const_twa_graph_ptr& aut,
|
||||
twa::prop_set p)
|
||||
twa::prop_set p)
|
||||
{
|
||||
return std::make_shared<twa_graph>(aut, p);
|
||||
}
|
||||
|
||||
inline twa_graph_ptr make_twa_graph(const const_twa_ptr& aut,
|
||||
twa::prop_set p)
|
||||
twa::prop_set p)
|
||||
{
|
||||
auto a = std::dynamic_pointer_cast<const twa_graph>(aut);
|
||||
if (a)
|
||||
|
|
|
|||
|
|
@ -83,58 +83,58 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
twa_succ_iterator_product_common(twa_succ_iterator* left,
|
||||
twa_succ_iterator* right,
|
||||
const twa_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: left_(left), right_(right), prod_(prod), pool_(pool)
|
||||
twa_succ_iterator* right,
|
||||
const twa_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: left_(left), right_(right), prod_(prod), pool_(pool)
|
||||
{
|
||||
}
|
||||
|
||||
void recycle(const const_twa_ptr& l, twa_succ_iterator* left,
|
||||
const_twa_ptr r, twa_succ_iterator* right)
|
||||
const_twa_ptr r, twa_succ_iterator* right)
|
||||
{
|
||||
l->release_iter(left_);
|
||||
left_ = left;
|
||||
r->release_iter(right_);
|
||||
right_ = right;
|
||||
l->release_iter(left_);
|
||||
left_ = left;
|
||||
r->release_iter(right_);
|
||||
right_ = right;
|
||||
}
|
||||
|
||||
virtual ~twa_succ_iterator_product_common()
|
||||
{
|
||||
delete left_;
|
||||
delete right_;
|
||||
delete left_;
|
||||
delete right_;
|
||||
}
|
||||
|
||||
virtual bool next_non_false_() = 0;
|
||||
|
||||
bool first()
|
||||
{
|
||||
if (!right_)
|
||||
return false;
|
||||
if (!right_)
|
||||
return false;
|
||||
|
||||
// If one of the two successor sets is empty initially, we
|
||||
// reset right_, so that done() can detect this situation
|
||||
// easily. (We choose to reset right_ because this variable
|
||||
// is already used by done().)
|
||||
if (!(left_->first() && right_->first()))
|
||||
{
|
||||
delete right_;
|
||||
right_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
return next_non_false_();
|
||||
// If one of the two successor sets is empty initially, we
|
||||
// reset right_, so that done() can detect this situation
|
||||
// easily. (We choose to reset right_ because this variable
|
||||
// is already used by done().)
|
||||
if (!(left_->first() && right_->first()))
|
||||
{
|
||||
delete right_;
|
||||
right_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
return next_non_false_();
|
||||
}
|
||||
|
||||
bool done() const
|
||||
{
|
||||
return !right_ || right_->done();
|
||||
return !right_ || right_->done();
|
||||
}
|
||||
|
||||
const state_product* dst() const
|
||||
{
|
||||
return new(pool_->allocate()) state_product(left_->dst(),
|
||||
right_->dst(),
|
||||
pool_);
|
||||
return new(pool_->allocate()) state_product(left_->dst(),
|
||||
right_->dst(),
|
||||
pool_);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -151,10 +151,10 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
twa_succ_iterator_product(twa_succ_iterator* left,
|
||||
twa_succ_iterator* right,
|
||||
const twa_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: twa_succ_iterator_product_common(left, right, prod, pool)
|
||||
twa_succ_iterator* right,
|
||||
const twa_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: twa_succ_iterator_product_common(left, right, prod, pool)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -164,46 +164,46 @@ namespace spot
|
|||
|
||||
bool step_()
|
||||
{
|
||||
if (left_->next())
|
||||
return true;
|
||||
left_->first();
|
||||
return right_->next();
|
||||
if (left_->next())
|
||||
return true;
|
||||
left_->first();
|
||||
return right_->next();
|
||||
}
|
||||
|
||||
bool next_non_false_()
|
||||
{
|
||||
assert(!done());
|
||||
do
|
||||
{
|
||||
bdd l = left_->cond();
|
||||
bdd r = right_->cond();
|
||||
bdd current_cond = l & r;
|
||||
assert(!done());
|
||||
do
|
||||
{
|
||||
bdd l = left_->cond();
|
||||
bdd r = right_->cond();
|
||||
bdd current_cond = l & r;
|
||||
|
||||
if (current_cond != bddfalse)
|
||||
{
|
||||
current_cond_ = current_cond;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
while (step_());
|
||||
return false;
|
||||
if (current_cond != bddfalse)
|
||||
{
|
||||
current_cond_ = current_cond;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
while (step_());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool next()
|
||||
{
|
||||
if (step_())
|
||||
return next_non_false_();
|
||||
return false;
|
||||
if (step_())
|
||||
return next_non_false_();
|
||||
return false;
|
||||
}
|
||||
|
||||
bdd cond() const
|
||||
{
|
||||
return current_cond_;
|
||||
return current_cond_;
|
||||
}
|
||||
|
||||
acc_cond::mark_t acc() const
|
||||
{
|
||||
return left_->acc() | (right_->acc() << prod_->left_acc().num_sets());
|
||||
return left_->acc() | (right_->acc() << prod_->left_acc().num_sets());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -217,10 +217,10 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
twa_succ_iterator_product_kripke(twa_succ_iterator* left,
|
||||
twa_succ_iterator* right,
|
||||
const twa_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: twa_succ_iterator_product_common(left, right, prod, pool)
|
||||
twa_succ_iterator* right,
|
||||
const twa_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: twa_succ_iterator_product_common(left, right, prod, pool)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -230,43 +230,43 @@ namespace spot
|
|||
|
||||
bool next_non_false_()
|
||||
{
|
||||
// All the transitions of left_ iterator have the
|
||||
// same label, because it is a Kripke structure.
|
||||
bdd l = left_->cond();
|
||||
assert(!right_->done());
|
||||
do
|
||||
{
|
||||
bdd r = right_->cond();
|
||||
bdd current_cond = l & r;
|
||||
// All the transitions of left_ iterator have the
|
||||
// same label, because it is a Kripke structure.
|
||||
bdd l = left_->cond();
|
||||
assert(!right_->done());
|
||||
do
|
||||
{
|
||||
bdd r = right_->cond();
|
||||
bdd current_cond = l & r;
|
||||
|
||||
if (current_cond != bddfalse)
|
||||
{
|
||||
current_cond_ = current_cond;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
while (right_->next());
|
||||
return false;
|
||||
if (current_cond != bddfalse)
|
||||
{
|
||||
current_cond_ = current_cond;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
while (right_->next());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool next()
|
||||
{
|
||||
if (left_->next())
|
||||
return true;
|
||||
left_->first();
|
||||
if (right_->next())
|
||||
return next_non_false_();
|
||||
return false;
|
||||
if (left_->next())
|
||||
return true;
|
||||
left_->first();
|
||||
if (right_->next())
|
||||
return next_non_false_();
|
||||
return false;
|
||||
}
|
||||
|
||||
bdd cond() const
|
||||
{
|
||||
return current_cond_;
|
||||
return current_cond_;
|
||||
}
|
||||
|
||||
acc_cond::mark_t acc() const
|
||||
{
|
||||
return right_->acc();
|
||||
return right_->acc();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -279,13 +279,13 @@ namespace spot
|
|||
// twa_product
|
||||
|
||||
twa_product::twa_product(const const_twa_ptr& left,
|
||||
const const_twa_ptr& right)
|
||||
const const_twa_ptr& right)
|
||||
: twa(left->get_dict()), left_(left), right_(right),
|
||||
pool_(sizeof(state_product))
|
||||
{
|
||||
if (left->get_dict() != right->get_dict())
|
||||
throw std::runtime_error("twa_product: left and right automata should "
|
||||
"share their bdd_dict");
|
||||
"share their bdd_dict");
|
||||
assert(get_dict() == right_->get_dict());
|
||||
|
||||
// If one of the side is a Kripke structure, it is easier to deal
|
||||
|
|
@ -293,16 +293,16 @@ namespace spot
|
|||
// computing the successors can be improved a bit).
|
||||
if (dynamic_cast<const kripke*>(left_.get()))
|
||||
{
|
||||
left_kripke_ = true;
|
||||
left_kripke_ = true;
|
||||
}
|
||||
else if (dynamic_cast<const kripke*>(right_.get()))
|
||||
{
|
||||
std::swap(left_, right_);
|
||||
left_kripke_ = true;
|
||||
std::swap(left_, right_);
|
||||
left_kripke_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
left_kripke_ = false;
|
||||
left_kripke_ = false;
|
||||
}
|
||||
|
||||
auto d = get_dict();
|
||||
|
|
@ -329,7 +329,7 @@ namespace spot
|
|||
{
|
||||
fixed_size_pool* p = const_cast<fixed_size_pool*>(&pool_);
|
||||
return new(p->allocate()) state_product(left_->get_init_state(),
|
||||
right_->get_init_state(), p);
|
||||
right_->get_init_state(), p);
|
||||
}
|
||||
|
||||
twa_succ_iterator*
|
||||
|
|
@ -342,11 +342,11 @@ namespace spot
|
|||
|
||||
if (iter_cache_)
|
||||
{
|
||||
twa_succ_iterator_product_common* it =
|
||||
down_cast<twa_succ_iterator_product_common*>(iter_cache_);
|
||||
it->recycle(left_, li, right_, ri);
|
||||
iter_cache_ = nullptr;
|
||||
return it;
|
||||
twa_succ_iterator_product_common* it =
|
||||
down_cast<twa_succ_iterator_product_common*>(iter_cache_);
|
||||
it->recycle(left_, li, right_, ri);
|
||||
iter_cache_ = nullptr;
|
||||
return it;
|
||||
}
|
||||
|
||||
fixed_size_pool* p = const_cast<fixed_size_pool*>(&pool_);
|
||||
|
|
@ -372,8 +372,8 @@ namespace spot
|
|||
const state_product* s = down_cast<const state_product*>(state);
|
||||
assert(s);
|
||||
return (left_->format_state(s->left())
|
||||
+ " * "
|
||||
+ right_->format_state(s->right()));
|
||||
+ " * "
|
||||
+ right_->format_state(s->right()));
|
||||
}
|
||||
|
||||
state*
|
||||
|
|
@ -393,9 +393,9 @@ namespace spot
|
|||
// twa_product_init
|
||||
|
||||
twa_product_init::twa_product_init(const const_twa_ptr& left,
|
||||
const const_twa_ptr& right,
|
||||
const state* left_init,
|
||||
const state* right_init)
|
||||
const const_twa_ptr& right,
|
||||
const state* left_init,
|
||||
const state* right_init)
|
||||
: twa_product(left, right),
|
||||
left_init_(left_init), right_init_(right_init)
|
||||
{
|
||||
|
|
@ -408,7 +408,7 @@ namespace spot
|
|||
{
|
||||
fixed_size_pool* p = const_cast<fixed_size_pool*>(&pool_);
|
||||
return new(p->allocate()) state_product(left_init_->clone(),
|
||||
right_init_->clone(), p);
|
||||
right_init_->clone(), p);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ namespace spot
|
|||
/// These states are acquired by spot::state_product, and will
|
||||
/// be destroyed on destruction.
|
||||
state_product(const state* left,
|
||||
const state* right,
|
||||
fixed_size_pool* pool)
|
||||
: left_(left), right_(right), count_(1), pool_(pool)
|
||||
const state* right,
|
||||
fixed_size_pool* pool)
|
||||
: left_(left), right_(right), count_(1), pool_(pool)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -68,8 +68,8 @@ namespace spot
|
|||
virtual state_product* clone() const override;
|
||||
|
||||
private:
|
||||
const state* left_; ///< State from the left automaton.
|
||||
const state* right_; ///< State from the right automaton.
|
||||
const state* left_; ///< State from the left automaton.
|
||||
const state* right_; ///< State from the right automaton.
|
||||
mutable unsigned count_;
|
||||
fixed_size_pool* pool_;
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
twa_product_init(const const_twa_ptr& left, const const_twa_ptr& right,
|
||||
const state* left_init, const state* right_init);
|
||||
const state* left_init, const state* right_init);
|
||||
virtual const state* get_init_state() const override;
|
||||
protected:
|
||||
const state* left_init_;
|
||||
|
|
@ -129,18 +129,18 @@ namespace spot
|
|||
|
||||
/// \brief on-the-fly TGBA product
|
||||
inline twa_product_ptr otf_product(const const_twa_ptr& left,
|
||||
const const_twa_ptr& right)
|
||||
const const_twa_ptr& right)
|
||||
{
|
||||
return std::make_shared<twa_product>(left, right);
|
||||
}
|
||||
|
||||
/// \brief on-the-fly TGBA product with forced initial states
|
||||
inline twa_product_ptr otf_product_at(const const_twa_ptr& left,
|
||||
const const_twa_ptr& right,
|
||||
const state* left_init,
|
||||
const state* right_init)
|
||||
const const_twa_ptr& right,
|
||||
const state* left_init,
|
||||
const state* right_init)
|
||||
{
|
||||
return std::make_shared<twa_product_init>(left, right,
|
||||
left_init, right_init);
|
||||
left_init, right_init);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,13 +116,13 @@ namespace spot
|
|||
trival prop_det = ref_->prop_deterministic();
|
||||
if (prop_det)
|
||||
{
|
||||
ref_deterministic_ = true;
|
||||
ref_deterministic_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Count the number of state even if we know that the
|
||||
// automaton is non-deterministic, as this can be used to
|
||||
// decide if two automata are non-isomorphic.
|
||||
// Count the number of state even if we know that the
|
||||
// automaton is non-deterministic, as this can be used to
|
||||
// decide if two automata are non-isomorphic.
|
||||
nondet_states_ = spot::count_nondet_states(ref_);
|
||||
ref_deterministic_ = (nondet_states_ == 0);
|
||||
}
|
||||
|
|
@ -136,12 +136,12 @@ namespace spot
|
|||
if (ref_deterministic_)
|
||||
{
|
||||
if (autdet || (!autdet && spot::is_deterministic(aut)))
|
||||
return are_isomorphic_det(ref_, aut);
|
||||
return are_isomorphic_det(ref_, aut);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (autdet || nondet_states_ != spot::count_nondet_states(aut))
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto tmp = make_twa_graph(aut, twa::prop_set::all());
|
||||
|
|
@ -159,7 +159,7 @@ namespace spot
|
|||
|
||||
bool
|
||||
isomorphism_checker::are_isomorphic(const const_twa_graph_ptr ref,
|
||||
const const_twa_graph_ptr aut)
|
||||
const const_twa_graph_ptr aut)
|
||||
{
|
||||
if (trivially_different(ref, aut))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ namespace spot
|
|||
/// \ingroup twa_misc
|
||||
/// \brief Check whether two automata are isomorphic.
|
||||
static bool are_isomorphic(const const_twa_graph_ptr ref,
|
||||
const const_twa_graph_ptr aut);
|
||||
const const_twa_graph_ptr aut);
|
||||
|
||||
private:
|
||||
bool is_isomorphic_(const const_twa_graph_ptr aut);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue