* iface/gspn/gspn.cc, src/ltlvisit/basicreduce.cc,
src/ltlvisit/destroy.cc, src/ltlvisit/dotty.cc,
src/ltlvisit/dump.cc, src/ltlvisit/length.cc,
src/ltlvisit/nenoform.cc, src/ltlvisit/reduce.cc,
src/ltlvisit/syntimpl.cc, src/ltlvisit/tostring.cc,
src/tgba/formula2bdd.cc, src/tgba/tgbabddconcreteproduct.cc,
src/tgba/tgbatba.cc, src/tgbaalgos/dotty.cc,
src/tgbaalgos/dupexp.cc, src/tgbaalgos/lbtt.cc,
src/tgbaalgos/ltl2tgba_lacim.cc, src/tgbaalgos/neverclaim.cc,
src/tgbaalgos/save.cc, src/tgbaalgos/stats.cc,
src/tgbaalgos/gtec/nsheap.cc, src/tgbaalgos/gtec/nsheap.hh:
Declare private classes and helper function in anonymous namespaces.
* HACKING, src/sanity/style.test: Document and check this.
Also check for trailing { after namespace or class.
* src/ltlast/predecl.hh, src/ltlast/visitor.hh,
src/tgba/tgbareduc.hh: Fix trailing {.
This commit is contained in:
parent
5176caf4d2
commit
7d27fd3796
28 changed files with 3128 additions and 3025 deletions
|
|
@ -28,51 +28,53 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
class dotty_bfs : public tgba_reachable_iterator_breadth_first
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
dotty_bfs(const tgba* a, std::ostream& os)
|
||||
: tgba_reachable_iterator_breadth_first(a), os_(os)
|
||||
class dotty_bfs : public tgba_reachable_iterator_breadth_first
|
||||
{
|
||||
}
|
||||
public:
|
||||
dotty_bfs(const tgba* a, std::ostream& os)
|
||||
: tgba_reachable_iterator_breadth_first(a), os_(os)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
start()
|
||||
{
|
||||
os_ << "digraph G {" << std::endl;
|
||||
os_ << " 0 [label=\"\", style=invis, height=0]" << std::endl;
|
||||
os_ << " 0 -> 1" << std::endl;
|
||||
}
|
||||
void
|
||||
start()
|
||||
{
|
||||
os_ << "digraph G {" << std::endl;
|
||||
os_ << " 0 [label=\"\", style=invis, height=0]" << std::endl;
|
||||
os_ << " 0 -> 1" << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
end()
|
||||
{
|
||||
os_ << "}" << std::endl;
|
||||
}
|
||||
void
|
||||
end()
|
||||
{
|
||||
os_ << "}" << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
process_state(const state* s, int n, tgba_succ_iterator*)
|
||||
{
|
||||
os_ << " " << n << " [label=\"";
|
||||
escape_str(os_, automata_->format_state(s)) << "\"]" << std::endl;
|
||||
}
|
||||
void
|
||||
process_state(const state* s, int n, tgba_succ_iterator*)
|
||||
{
|
||||
os_ << " " << n << " [label=\"";
|
||||
escape_str(os_, automata_->format_state(s)) << "\"]" << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
process_link(int in, int out, const tgba_succ_iterator* si)
|
||||
{
|
||||
os_ << " " << in << " -> " << out << " [label=\"";
|
||||
escape_str(os_, bdd_format_formula(automata_->get_dict(),
|
||||
si->current_condition())) << "\\n";
|
||||
escape_str(os_,
|
||||
bdd_format_accset(automata_->get_dict(),
|
||||
si->current_acceptance_conditions()))
|
||||
<< "\"]" << std::endl;
|
||||
}
|
||||
void
|
||||
process_link(int in, int out, const tgba_succ_iterator* si)
|
||||
{
|
||||
os_ << " " << in << " -> " << out << " [label=\"";
|
||||
escape_str(os_, bdd_format_formula(automata_->get_dict(),
|
||||
si->current_condition())) << "\\n";
|
||||
escape_str(os_,
|
||||
bdd_format_accset(automata_->get_dict(),
|
||||
si->current_acceptance_conditions()))
|
||||
<< "\"]" << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream& os_;
|
||||
};
|
||||
private:
|
||||
std::ostream& os_;
|
||||
};
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
dotty_reachable(std::ostream& os, const tgba* g)
|
||||
|
|
|
|||
|
|
@ -25,73 +25,77 @@
|
|||
#include <map>
|
||||
#include "reachiter.hh"
|
||||
|
||||
namespace spot {
|
||||
|
||||
template <class T>
|
||||
class dupexp_iter: public T
|
||||
namespace spot
|
||||
{
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
dupexp_iter(const tgba* a)
|
||||
: T(a), out_(new tgba_explicit(a->get_dict()))
|
||||
template <class T>
|
||||
class dupexp_iter: public T
|
||||
{
|
||||
}
|
||||
public:
|
||||
dupexp_iter(const tgba* a)
|
||||
: T(a), out_(new tgba_explicit(a->get_dict()))
|
||||
{
|
||||
}
|
||||
|
||||
tgba_explicit*
|
||||
result()
|
||||
{
|
||||
return out_;
|
||||
}
|
||||
tgba_explicit*
|
||||
result()
|
||||
{
|
||||
return out_;
|
||||
}
|
||||
|
||||
void
|
||||
process_state(const state* s, int n, tgba_succ_iterator*)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "(#" << n << ") " << this->automata_->format_state(s);
|
||||
name_[n] = os.str();
|
||||
}
|
||||
void
|
||||
process_state(const state* s, int n, tgba_succ_iterator*)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "(#" << n << ") " << this->automata_->format_state(s);
|
||||
name_[n] = os.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
declare_state(const state* s, int n)
|
||||
{
|
||||
std::string str;
|
||||
name_map_::const_iterator i = name_.find(n);
|
||||
if (i == name_.end())
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "(#" << n << ") " << this->automata_->format_state(s);
|
||||
name_[n] = str = os.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
str = i->second;
|
||||
}
|
||||
delete s;
|
||||
return str;
|
||||
}
|
||||
std::string
|
||||
declare_state(const state* s, int n)
|
||||
{
|
||||
std::string str;
|
||||
name_map_::const_iterator i = name_.find(n);
|
||||
if (i == name_.end())
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "(#" << n << ") " << this->automata_->format_state(s);
|
||||
name_[n] = str = os.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
str = i->second;
|
||||
}
|
||||
delete s;
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
process_link(int in, int out, const tgba_succ_iterator* si)
|
||||
{
|
||||
// We might need to format out before process_state is called.
|
||||
name_map_::const_iterator i = name_.find(out);
|
||||
if (i == name_.end())
|
||||
{
|
||||
const state* s = si->current_state();
|
||||
process_state(s, out, 0);
|
||||
delete s;
|
||||
}
|
||||
void
|
||||
process_link(int in, int out, const tgba_succ_iterator* si)
|
||||
{
|
||||
// We might need to format out before process_state is called.
|
||||
name_map_::const_iterator i = name_.find(out);
|
||||
if (i == name_.end())
|
||||
{
|
||||
const state* s = si->current_state();
|
||||
process_state(s, out, 0);
|
||||
delete s;
|
||||
}
|
||||
|
||||
tgba_explicit::transition* t =
|
||||
out_->create_transition(name_[in], name_[out]);
|
||||
out_->add_conditions(t, si->current_condition());
|
||||
out_->add_acceptance_conditions(t, si->current_acceptance_conditions());
|
||||
}
|
||||
tgba_explicit::transition* t =
|
||||
out_->create_transition(name_[in], name_[out]);
|
||||
out_->add_conditions(t, si->current_condition());
|
||||
out_->add_acceptance_conditions(t, si->current_acceptance_conditions());
|
||||
}
|
||||
|
||||
private:
|
||||
tgba_explicit* out_;
|
||||
typedef std::map<int, std::string> name_map_;
|
||||
std::map<int, std::string> name_;
|
||||
};
|
||||
private:
|
||||
tgba_explicit* out_;
|
||||
typedef std::map<int, std::string> name_map_;
|
||||
std::map<int, std::string> name_;
|
||||
};
|
||||
|
||||
} // anonymous
|
||||
|
||||
tgba_explicit*
|
||||
tgba_dupexp_bfs(const tgba* aut)
|
||||
|
|
|
|||
|
|
@ -23,54 +23,57 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
class numbered_state_heap_hash_map_const_iterator :
|
||||
public numbered_state_heap_const_iterator
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
numbered_state_heap_hash_map_const_iterator
|
||||
(const numbered_state_heap_hash_map::hash_type& h)
|
||||
: numbered_state_heap_const_iterator(), h(h)
|
||||
class numbered_state_heap_hash_map_const_iterator:
|
||||
public numbered_state_heap_const_iterator
|
||||
{
|
||||
}
|
||||
public:
|
||||
numbered_state_heap_hash_map_const_iterator
|
||||
(const numbered_state_heap_hash_map::hash_type& h)
|
||||
: numbered_state_heap_const_iterator(), h(h)
|
||||
{
|
||||
}
|
||||
|
||||
~numbered_state_heap_hash_map_const_iterator()
|
||||
{
|
||||
}
|
||||
~numbered_state_heap_hash_map_const_iterator()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
first()
|
||||
{
|
||||
i = h.begin();
|
||||
}
|
||||
virtual void
|
||||
first()
|
||||
{
|
||||
i = h.begin();
|
||||
}
|
||||
|
||||
virtual void
|
||||
next()
|
||||
{
|
||||
++i;
|
||||
}
|
||||
virtual void
|
||||
next()
|
||||
{
|
||||
++i;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
done() const
|
||||
{
|
||||
return i == h.end();
|
||||
}
|
||||
virtual bool
|
||||
done() const
|
||||
{
|
||||
return i == h.end();
|
||||
}
|
||||
|
||||
virtual const state*
|
||||
get_state() const
|
||||
{
|
||||
return i->first;
|
||||
}
|
||||
virtual const state*
|
||||
get_state() const
|
||||
{
|
||||
return i->first;
|
||||
}
|
||||
|
||||
virtual int
|
||||
get_index() const
|
||||
{
|
||||
return i->second;
|
||||
}
|
||||
virtual int
|
||||
get_index() const
|
||||
{
|
||||
return i->second;
|
||||
}
|
||||
|
||||
private:
|
||||
numbered_state_heap_hash_map::hash_type::const_iterator i;
|
||||
const numbered_state_heap_hash_map::hash_type& h;
|
||||
};
|
||||
private:
|
||||
numbered_state_heap_hash_map::hash_type::const_iterator i;
|
||||
const numbered_state_heap_hash_map::hash_type& h;
|
||||
};
|
||||
} // anonymous
|
||||
|
||||
numbered_state_heap_hash_map::~numbered_state_heap_hash_map()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -119,12 +119,11 @@ namespace spot
|
|||
virtual int size() const;
|
||||
|
||||
virtual numbered_state_heap_const_iterator* iterator() const;
|
||||
protected:
|
||||
|
||||
typedef Sgi::hash_map<const state*, int,
|
||||
state_ptr_hash, state_ptr_equal> hash_type;
|
||||
protected:
|
||||
hash_type h; ///< Map of visited states.
|
||||
|
||||
friend class numbered_state_heap_hash_map_const_iterator;
|
||||
};
|
||||
|
||||
/// \brief Factory for numbered_state_heap_hash_map.
|
||||
|
|
|
|||
|
|
@ -30,129 +30,132 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
// At some point we'll need to print an acceptance set into LBTT's
|
||||
// format. LBTT expects numbered acceptance sets, so first we'll
|
||||
// number each acceptance condition, and latter when we have to print
|
||||
// them we'll just have to look up each of them.
|
||||
class acceptance_cond_splitter
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
acceptance_cond_splitter(bdd all_acc)
|
||||
// At some point we'll need to print an acceptance set into LBTT's
|
||||
// format. LBTT expects numbered acceptance sets, so first we'll
|
||||
// number each acceptance condition, and latter when we have to print
|
||||
// them we'll just have to look up each of them.
|
||||
class acceptance_cond_splitter
|
||||
{
|
||||
unsigned count = 0;
|
||||
while (all_acc != bddfalse)
|
||||
{
|
||||
bdd acc = bdd_satone(all_acc);
|
||||
all_acc -= acc;
|
||||
sm[acc] = count++;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
split(std::ostream& os, bdd b)
|
||||
{
|
||||
while (b != bddfalse)
|
||||
{
|
||||
bdd acc = bdd_satone(b);
|
||||
b -= acc;
|
||||
os << sm[acc] << " ";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
unsigned
|
||||
count() const
|
||||
{
|
||||
return sm.size();
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::map<bdd, unsigned, bdd_less_than> split_map;
|
||||
split_map sm;
|
||||
};
|
||||
|
||||
// Convert a BDD formula to the syntax used by LBTT's transition guards.
|
||||
// Conjunctions are printed by bdd_format_sat, so we just have
|
||||
// to handle the other cases.
|
||||
static std::string
|
||||
bdd_to_lbtt(bdd b, const bdd_dict* d)
|
||||
{
|
||||
if (b == bddfalse)
|
||||
return "f";
|
||||
else if (b == bddtrue)
|
||||
return "t";
|
||||
else
|
||||
public:
|
||||
acceptance_cond_splitter(bdd all_acc)
|
||||
{
|
||||
bdd cube = bdd_satone(b);
|
||||
b -= cube;
|
||||
if (b != bddfalse)
|
||||
unsigned count = 0;
|
||||
while (all_acc != bddfalse)
|
||||
{
|
||||
return "| " + bdd_to_lbtt(b, d) + " " + bdd_to_lbtt(cube, d);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string res = "";
|
||||
for (int count = bdd_nodecount(cube); count > 1; --count)
|
||||
res += "& ";
|
||||
return res + bdd_format_sat(d, cube);
|
||||
bdd acc = bdd_satone(all_acc);
|
||||
all_acc -= acc;
|
||||
sm[acc] = count++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
std::ostream&
|
||||
split(std::ostream& os, bdd b)
|
||||
{
|
||||
while (b != bddfalse)
|
||||
{
|
||||
bdd acc = bdd_satone(b);
|
||||
b -= acc;
|
||||
os << sm[acc] << " ";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
class lbtt_bfs : public tgba_reachable_iterator_breadth_first
|
||||
{
|
||||
public:
|
||||
lbtt_bfs(const tgba* a, std::ostream& os)
|
||||
: tgba_reachable_iterator_breadth_first(a),
|
||||
os_(os),
|
||||
acc_count_(0),
|
||||
acs_(a->all_acceptance_conditions())
|
||||
unsigned
|
||||
count() const
|
||||
{
|
||||
return sm.size();
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::map<bdd, unsigned, bdd_less_than> split_map;
|
||||
split_map sm;
|
||||
};
|
||||
|
||||
// Convert a BDD formula to the syntax used by LBTT's transition guards.
|
||||
// Conjunctions are printed by bdd_format_sat, so we just have
|
||||
// to handle the other cases.
|
||||
static std::string
|
||||
bdd_to_lbtt(bdd b, const bdd_dict* d)
|
||||
{
|
||||
// Count the number of acceptance_conditions.
|
||||
bdd all = a->all_acceptance_conditions();
|
||||
while (all != bddfalse)
|
||||
{
|
||||
bdd one = bdd_satone(all);
|
||||
all -= one;
|
||||
++acc_count_;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
process_state(const state*, int n, tgba_succ_iterator*)
|
||||
{
|
||||
--n;
|
||||
if (n == 0)
|
||||
body_ << "0 1" << std::endl;
|
||||
if (b == bddfalse)
|
||||
return "f";
|
||||
else if (b == bddtrue)
|
||||
return "t";
|
||||
else
|
||||
body_ << "-1" << std::endl << n << " 0" << std::endl;
|
||||
{
|
||||
bdd cube = bdd_satone(b);
|
||||
b -= cube;
|
||||
if (b != bddfalse)
|
||||
{
|
||||
return "| " + bdd_to_lbtt(b, d) + " " + bdd_to_lbtt(cube, d);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string res = "";
|
||||
for (int count = bdd_nodecount(cube); count > 1; --count)
|
||||
res += "& ";
|
||||
return res + bdd_format_sat(d, cube);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
process_link(int, int out, const tgba_succ_iterator* si)
|
||||
class lbtt_bfs : public tgba_reachable_iterator_breadth_first
|
||||
{
|
||||
body_ << out - 1 << " ";
|
||||
acs_.split(body_, si->current_acceptance_conditions());
|
||||
body_ << "-1 " << bdd_to_lbtt(si->current_condition(),
|
||||
automata_->get_dict()) << std::endl;
|
||||
}
|
||||
public:
|
||||
lbtt_bfs(const tgba* a, std::ostream& os)
|
||||
: tgba_reachable_iterator_breadth_first(a),
|
||||
os_(os),
|
||||
acc_count_(0),
|
||||
acs_(a->all_acceptance_conditions())
|
||||
|
||||
void
|
||||
end()
|
||||
{
|
||||
os_ << seen.size() << " " << acc_count_ << "t" << std::endl
|
||||
<< body_.str() << "-1" << std::endl;
|
||||
}
|
||||
{
|
||||
// Count the number of acceptance_conditions.
|
||||
bdd all = a->all_acceptance_conditions();
|
||||
while (all != bddfalse)
|
||||
{
|
||||
bdd one = bdd_satone(all);
|
||||
all -= one;
|
||||
++acc_count_;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream& os_;
|
||||
std::ostringstream body_;
|
||||
unsigned acc_count_;
|
||||
acceptance_cond_splitter acs_;
|
||||
};
|
||||
void
|
||||
process_state(const state*, int n, tgba_succ_iterator*)
|
||||
{
|
||||
--n;
|
||||
if (n == 0)
|
||||
body_ << "0 1" << std::endl;
|
||||
else
|
||||
body_ << "-1" << std::endl << n << " 0" << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
process_link(int, int out, const tgba_succ_iterator* si)
|
||||
{
|
||||
body_ << out - 1 << " ";
|
||||
acs_.split(body_, si->current_acceptance_conditions());
|
||||
body_ << "-1 " << bdd_to_lbtt(si->current_condition(),
|
||||
automata_->get_dict()) << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
end()
|
||||
{
|
||||
os_ << seen.size() << " " << acc_count_ << "t" << std::endl
|
||||
<< body_.str() << "-1" << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream& os_;
|
||||
std::ostringstream body_;
|
||||
unsigned acc_count_;
|
||||
acceptance_cond_splitter acs_;
|
||||
};
|
||||
|
||||
} // anonymous
|
||||
|
||||
std::ostream&
|
||||
lbtt_reachable(std::ostream& os, const tgba* g)
|
||||
|
|
@ -161,6 +164,4 @@ namespace spot
|
|||
b.run();
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,225 +31,228 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
using namespace ltl;
|
||||
|
||||
/// \brief Recursively translate a formula into a BDD.
|
||||
///
|
||||
/// The algorithm used here is adapted from Jean-Michel Couvreur's
|
||||
/// Probataf tool.
|
||||
class ltl_trad_visitor: public const_visitor
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
ltl_trad_visitor(tgba_bdd_concrete_factory& fact, bool root = false)
|
||||
: fact_(fact), root_(root)
|
||||
{
|
||||
}
|
||||
using namespace ltl;
|
||||
|
||||
virtual
|
||||
~ltl_trad_visitor()
|
||||
/// \brief Recursively translate a formula into a BDD.
|
||||
///
|
||||
/// The algorithm used here is adapted from Jean-Michel Couvreur's
|
||||
/// Probataf tool.
|
||||
class ltl_trad_visitor: public const_visitor
|
||||
{
|
||||
}
|
||||
public:
|
||||
ltl_trad_visitor(tgba_bdd_concrete_factory& fact, bool root = false)
|
||||
: fact_(fact), root_(root)
|
||||
{
|
||||
}
|
||||
|
||||
bdd
|
||||
result()
|
||||
{
|
||||
return res_;
|
||||
}
|
||||
virtual
|
||||
~ltl_trad_visitor()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
visit(const atomic_prop* node)
|
||||
{
|
||||
res_ = bdd_ithvar(fact_.create_atomic_prop(node));
|
||||
}
|
||||
bdd
|
||||
result()
|
||||
{
|
||||
return res_;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const constant* node)
|
||||
{
|
||||
switch (node->val())
|
||||
{
|
||||
case constant::True:
|
||||
res_ = bddtrue;
|
||||
return;
|
||||
case constant::False:
|
||||
res_ = bddfalse;
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
void
|
||||
visit(const atomic_prop* node)
|
||||
{
|
||||
res_ = bdd_ithvar(fact_.create_atomic_prop(node));
|
||||
}
|
||||
|
||||
void
|
||||
visit(const unop* node)
|
||||
{
|
||||
switch (node->op())
|
||||
{
|
||||
case unop::F:
|
||||
void
|
||||
visit(const constant* node)
|
||||
{
|
||||
switch (node->val())
|
||||
{
|
||||
/*
|
||||
Fx <=> x | XFx
|
||||
In other words:
|
||||
now <=> x | next
|
||||
*/
|
||||
int v = fact_.create_state(node);
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
bdd x = recurse(node->child());
|
||||
fact_.constrain_relation(bdd_apply(now, x | next, bddop_biimp));
|
||||
/*
|
||||
`x | next', doesn't actually encode the fact that x
|
||||
should be fulfilled eventually. We ensure this by
|
||||
creating a new generalized Büchi acceptance set, Acc[x],
|
||||
and leave out of this set any transition going off NOW
|
||||
without checking X. Such acceptance conditions are
|
||||
checked for during the emptiness check.
|
||||
*/
|
||||
fact_.declare_acceptance_condition(x | !now, node->child());
|
||||
res_ = now;
|
||||
case constant::True:
|
||||
res_ = bddtrue;
|
||||
return;
|
||||
case constant::False:
|
||||
res_ = bddfalse;
|
||||
return;
|
||||
}
|
||||
case unop::G:
|
||||
{
|
||||
bdd child = recurse(node->child());
|
||||
// If G occurs at the top of the formula we don't
|
||||
// need Now/Next variables. We just constrain
|
||||
// the relation so that the child always happens.
|
||||
// This saves 2 BDD variables.
|
||||
if (root_)
|
||||
{
|
||||
fact_.constrain_relation(child);
|
||||
res_ = child;
|
||||
return;
|
||||
}
|
||||
// Gx <=> x && XGx
|
||||
int v = fact_.create_state(node);
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
fact_.constrain_relation(bdd_apply(now, child & next,
|
||||
bddop_biimp));
|
||||
res_ = now;
|
||||
return;
|
||||
}
|
||||
case unop::Not:
|
||||
{
|
||||
res_ = bdd_not(recurse(node->child()));
|
||||
return;
|
||||
}
|
||||
case unop::X:
|
||||
{
|
||||
int v = fact_.create_state(node->child());
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
fact_.constrain_relation(bdd_apply(now, recurse(node->child()),
|
||||
bddop_biimp));
|
||||
res_ = next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const binop* node)
|
||||
{
|
||||
bdd f1 = recurse(node->first());
|
||||
bdd f2 = recurse(node->second());
|
||||
|
||||
switch (node->op())
|
||||
{
|
||||
case binop::Xor:
|
||||
res_ = bdd_apply(f1, f2, bddop_xor);
|
||||
return;
|
||||
case binop::Implies:
|
||||
res_ = bdd_apply(f1, f2, bddop_imp);
|
||||
return;
|
||||
case binop::Equiv:
|
||||
res_ = bdd_apply(f1, f2, bddop_biimp);
|
||||
return;
|
||||
case binop::U:
|
||||
void
|
||||
visit(const unop* node)
|
||||
{
|
||||
switch (node->op())
|
||||
{
|
||||
/*
|
||||
f1 U f2 <=> f2 | (f1 & X(f1 U f2))
|
||||
In other words:
|
||||
now <=> f2 | (f1 & next)
|
||||
*/
|
||||
int v = fact_.create_state(node);
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
fact_.constrain_relation(bdd_apply(now, f2 | (f1 & next),
|
||||
bddop_biimp));
|
||||
/*
|
||||
The rightmost conjunction, f1 & next, doesn't actually
|
||||
encode the fact that f2 should be fulfilled eventually.
|
||||
We declare an acceptance condition for this purpose (see
|
||||
the comment in the unop::F case).
|
||||
*/
|
||||
fact_.declare_acceptance_condition(f2 | !now, node->second());
|
||||
res_ = now;
|
||||
return;
|
||||
case unop::F:
|
||||
{
|
||||
/*
|
||||
Fx <=> x | XFx
|
||||
In other words:
|
||||
now <=> x | next
|
||||
*/
|
||||
int v = fact_.create_state(node);
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
bdd x = recurse(node->child());
|
||||
fact_.constrain_relation(bdd_apply(now, x | next, bddop_biimp));
|
||||
/*
|
||||
`x | next', doesn't actually encode the fact that x
|
||||
should be fulfilled eventually. We ensure this by
|
||||
creating a new generalized Büchi acceptance set, Acc[x],
|
||||
and leave out of this set any transition going off NOW
|
||||
without checking X. Such acceptance conditions are
|
||||
checked for during the emptiness check.
|
||||
*/
|
||||
fact_.declare_acceptance_condition(x | !now, node->child());
|
||||
res_ = now;
|
||||
return;
|
||||
}
|
||||
case unop::G:
|
||||
{
|
||||
bdd child = recurse(node->child());
|
||||
// If G occurs at the top of the formula we don't
|
||||
// need Now/Next variables. We just constrain
|
||||
// the relation so that the child always happens.
|
||||
// This saves 2 BDD variables.
|
||||
if (root_)
|
||||
{
|
||||
fact_.constrain_relation(child);
|
||||
res_ = child;
|
||||
return;
|
||||
}
|
||||
// Gx <=> x && XGx
|
||||
int v = fact_.create_state(node);
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
fact_.constrain_relation(bdd_apply(now, child & next,
|
||||
bddop_biimp));
|
||||
res_ = now;
|
||||
return;
|
||||
}
|
||||
case unop::Not:
|
||||
{
|
||||
res_ = bdd_not(recurse(node->child()));
|
||||
return;
|
||||
}
|
||||
case unop::X:
|
||||
{
|
||||
int v = fact_.create_state(node->child());
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
fact_.constrain_relation(bdd_apply(now, recurse(node->child()),
|
||||
bddop_biimp));
|
||||
res_ = next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case binop::R:
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const binop* node)
|
||||
{
|
||||
bdd f1 = recurse(node->first());
|
||||
bdd f2 = recurse(node->second());
|
||||
|
||||
switch (node->op())
|
||||
{
|
||||
/*
|
||||
f1 R f2 <=> f2 & (f1 | X(f1 R f2))
|
||||
In other words:
|
||||
now <=> f2 & (f1 | next)
|
||||
*/
|
||||
int v = fact_.create_state(node);
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
fact_.constrain_relation(bdd_apply(now, f2 & (f1 | next),
|
||||
bddop_biimp));
|
||||
res_ = now;
|
||||
case binop::Xor:
|
||||
res_ = bdd_apply(f1, f2, bddop_xor);
|
||||
return;
|
||||
case binop::Implies:
|
||||
res_ = bdd_apply(f1, f2, bddop_imp);
|
||||
return;
|
||||
case binop::Equiv:
|
||||
res_ = bdd_apply(f1, f2, bddop_biimp);
|
||||
return;
|
||||
case binop::U:
|
||||
{
|
||||
/*
|
||||
f1 U f2 <=> f2 | (f1 & X(f1 U f2))
|
||||
In other words:
|
||||
now <=> f2 | (f1 & next)
|
||||
*/
|
||||
int v = fact_.create_state(node);
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
fact_.constrain_relation(bdd_apply(now, f2 | (f1 & next),
|
||||
bddop_biimp));
|
||||
/*
|
||||
The rightmost conjunction, f1 & next, doesn't actually
|
||||
encode the fact that f2 should be fulfilled eventually.
|
||||
We declare an acceptance condition for this purpose (see
|
||||
the comment in the unop::F case).
|
||||
*/
|
||||
fact_.declare_acceptance_condition(f2 | !now, node->second());
|
||||
res_ = now;
|
||||
return;
|
||||
}
|
||||
case binop::R:
|
||||
{
|
||||
/*
|
||||
f1 R f2 <=> f2 & (f1 | X(f1 R f2))
|
||||
In other words:
|
||||
now <=> f2 & (f1 | next)
|
||||
*/
|
||||
int v = fact_.create_state(node);
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
fact_.constrain_relation(bdd_apply(now, f2 & (f1 | next),
|
||||
bddop_biimp));
|
||||
res_ = now;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const multop* node)
|
||||
{
|
||||
int op = -1;
|
||||
bool root = false;
|
||||
switch (node->op())
|
||||
{
|
||||
case multop::And:
|
||||
op = bddop_and;
|
||||
res_ = bddtrue;
|
||||
// When the root formula is a conjunction it's ok to
|
||||
// consider all children as root formulae. This allows the
|
||||
// root-G trick to save many more variable. (See the
|
||||
// translation of G.)
|
||||
root = root_;
|
||||
break;
|
||||
case multop::Or:
|
||||
op = bddop_or;
|
||||
res_ = bddfalse;
|
||||
break;
|
||||
}
|
||||
assert(op != -1);
|
||||
unsigned s = node->size();
|
||||
for (unsigned n = 0; n < s; ++n)
|
||||
{
|
||||
res_ = bdd_apply(res_, recurse(node->nth(n), root), op);
|
||||
}
|
||||
}
|
||||
void
|
||||
visit(const multop* node)
|
||||
{
|
||||
int op = -1;
|
||||
bool root = false;
|
||||
switch (node->op())
|
||||
{
|
||||
case multop::And:
|
||||
op = bddop_and;
|
||||
res_ = bddtrue;
|
||||
// When the root formula is a conjunction it's ok to
|
||||
// consider all children as root formulae. This allows the
|
||||
// root-G trick to save many more variable. (See the
|
||||
// translation of G.)
|
||||
root = root_;
|
||||
break;
|
||||
case multop::Or:
|
||||
op = bddop_or;
|
||||
res_ = bddfalse;
|
||||
break;
|
||||
}
|
||||
assert(op != -1);
|
||||
unsigned s = node->size();
|
||||
for (unsigned n = 0; n < s; ++n)
|
||||
{
|
||||
res_ = bdd_apply(res_, recurse(node->nth(n), root), op);
|
||||
}
|
||||
}
|
||||
|
||||
bdd
|
||||
recurse(const formula* f, bool root = false)
|
||||
{
|
||||
ltl_trad_visitor v(fact_, root);
|
||||
f->accept(v);
|
||||
return v.result();
|
||||
}
|
||||
bdd
|
||||
recurse(const formula* f, bool root = false)
|
||||
{
|
||||
ltl_trad_visitor v(fact_, root);
|
||||
f->accept(v);
|
||||
return v.result();
|
||||
}
|
||||
|
||||
private:
|
||||
bdd res_;
|
||||
tgba_bdd_concrete_factory& fact_;
|
||||
bool root_;
|
||||
};
|
||||
private:
|
||||
bdd res_;
|
||||
tgba_bdd_concrete_factory& fact_;
|
||||
bool root_;
|
||||
};
|
||||
} // anonymous
|
||||
|
||||
tgba_bdd_concrete*
|
||||
ltl_to_tgba_lacim(const ltl::formula* f, bdd_dict* dict)
|
||||
|
|
|
|||
|
|
@ -32,153 +32,155 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
class never_claim_bfs : public tgba_reachable_iterator_breadth_first
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
never_claim_bfs(const tgba_tba_proxy* a, std::ostream& os,
|
||||
const ltl::formula* f)
|
||||
: tgba_reachable_iterator_breadth_first(a),
|
||||
os_(os), f_(f), accept_all_(-1), fi_needed_(false)
|
||||
class never_claim_bfs : public tgba_reachable_iterator_breadth_first
|
||||
{
|
||||
}
|
||||
public:
|
||||
never_claim_bfs(const tgba_tba_proxy* a, std::ostream& os,
|
||||
const ltl::formula* f)
|
||||
: tgba_reachable_iterator_breadth_first(a),
|
||||
os_(os), f_(f), accept_all_(-1), fi_needed_(false)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
start()
|
||||
{
|
||||
os_ << "never {";
|
||||
if (f_)
|
||||
{
|
||||
os_ << " /* ";
|
||||
to_string(f_, os_);
|
||||
os_ << " */";
|
||||
}
|
||||
os_ << std::endl;
|
||||
init_ = automata_->get_init_state();
|
||||
}
|
||||
void
|
||||
start()
|
||||
{
|
||||
os_ << "never {";
|
||||
if (f_)
|
||||
{
|
||||
os_ << " /* ";
|
||||
to_string(f_, os_);
|
||||
os_ << " */";
|
||||
}
|
||||
os_ << std::endl;
|
||||
init_ = automata_->get_init_state();
|
||||
}
|
||||
|
||||
void
|
||||
end()
|
||||
{
|
||||
if (fi_needed_)
|
||||
os_ << " fi;" << std::endl;
|
||||
if (accept_all_ != -1)
|
||||
{
|
||||
os_ << "accept_all:" << std::endl;
|
||||
os_ << " skip" << std::endl;
|
||||
}
|
||||
os_ << "}" << std::endl;
|
||||
delete init_;
|
||||
}
|
||||
void
|
||||
end()
|
||||
{
|
||||
if (fi_needed_)
|
||||
os_ << " fi;" << std::endl;
|
||||
if (accept_all_ != -1)
|
||||
{
|
||||
os_ << "accept_all:" << std::endl;
|
||||
os_ << " skip" << std::endl;
|
||||
}
|
||||
os_ << "}" << std::endl;
|
||||
delete init_;
|
||||
}
|
||||
|
||||
bool
|
||||
state_is_accepting(const state *s)
|
||||
{
|
||||
return
|
||||
dynamic_cast<const tgba_tba_proxy*>(automata_)->state_is_accepting(s);
|
||||
}
|
||||
bool
|
||||
state_is_accepting(const state *s)
|
||||
{
|
||||
return
|
||||
dynamic_cast<const tgba_tba_proxy*>(automata_)->state_is_accepting(s);
|
||||
}
|
||||
|
||||
std::string
|
||||
get_state_label(const state* s, int n)
|
||||
{
|
||||
std::string label;
|
||||
if (s->compare(init_) == 0)
|
||||
if (state_is_accepting(s))
|
||||
label = "accept_init";
|
||||
else
|
||||
label = "T0_init";
|
||||
else
|
||||
{
|
||||
std::ostringstream ost;
|
||||
ost << n;
|
||||
std::string ns(ost.str());
|
||||
std::string
|
||||
get_state_label(const state* s, int n)
|
||||
{
|
||||
std::string label;
|
||||
if (s->compare(init_) == 0)
|
||||
if (state_is_accepting(s))
|
||||
label = "accept_init";
|
||||
else
|
||||
label = "T0_init";
|
||||
else
|
||||
{
|
||||
std::ostringstream ost;
|
||||
ost << n;
|
||||
std::string ns(ost.str());
|
||||
|
||||
if (state_is_accepting(s))
|
||||
{
|
||||
tgba_succ_iterator* it = automata_->succ_iter(s);
|
||||
it->first();
|
||||
if (it->done())
|
||||
label = "accept_S" + ns;
|
||||
else
|
||||
{
|
||||
state* current = it->current_state();
|
||||
if (it->current_condition() != bddtrue
|
||||
|| s->compare(current) != 0)
|
||||
label = "accept_S" + ns;
|
||||
else
|
||||
label = "accept_all";
|
||||
delete current;
|
||||
}
|
||||
delete it;
|
||||
}
|
||||
else
|
||||
label = "T0_S" + ns;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
if (state_is_accepting(s))
|
||||
{
|
||||
tgba_succ_iterator* it = automata_->succ_iter(s);
|
||||
it->first();
|
||||
if (it->done())
|
||||
label = "accept_S" + ns;
|
||||
else
|
||||
{
|
||||
state* current = it->current_state();
|
||||
if (it->current_condition() != bddtrue
|
||||
|| s->compare(current) != 0)
|
||||
label = "accept_S" + ns;
|
||||
else
|
||||
label = "accept_all";
|
||||
delete current;
|
||||
}
|
||||
delete it;
|
||||
}
|
||||
else
|
||||
label = "T0_S" + ns;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
void
|
||||
process_state(const state* s, int n, tgba_succ_iterator*)
|
||||
{
|
||||
tgba_succ_iterator* it = automata_->succ_iter(s);
|
||||
it->first();
|
||||
if (it->done())
|
||||
{
|
||||
if (fi_needed_ != 0)
|
||||
os_ << " fi;" << std::endl;
|
||||
os_ << get_state_label(s, n) << ": ";
|
||||
os_ << "/* " << automata_->format_state(s) << " */";
|
||||
os_ << std::endl;
|
||||
os_ << " if" << std::endl;
|
||||
os_ << " :: (0) -> goto " << get_state_label(s, n) << std::endl;
|
||||
fi_needed_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
state* current =it->current_state();
|
||||
if (state_is_accepting(s)
|
||||
&& it->current_condition() == bddtrue
|
||||
&& s->compare(init_) != 0
|
||||
&& s->compare(current) == 0)
|
||||
accept_all_ = n;
|
||||
else
|
||||
{
|
||||
if (fi_needed_)
|
||||
os_ << " fi;" << std::endl;
|
||||
os_ << get_state_label(s, n) << ": ";
|
||||
os_ << "/* " << automata_->format_state(s) << " */";
|
||||
os_ << std::endl;
|
||||
os_ << " if" << std::endl;
|
||||
fi_needed_ = true;
|
||||
}
|
||||
delete current;
|
||||
}
|
||||
delete it;
|
||||
}
|
||||
void
|
||||
process_state(const state* s, int n, tgba_succ_iterator*)
|
||||
{
|
||||
tgba_succ_iterator* it = automata_->succ_iter(s);
|
||||
it->first();
|
||||
if (it->done())
|
||||
{
|
||||
if (fi_needed_ != 0)
|
||||
os_ << " fi;" << std::endl;
|
||||
os_ << get_state_label(s, n) << ": ";
|
||||
os_ << "/* " << automata_->format_state(s) << " */";
|
||||
os_ << std::endl;
|
||||
os_ << " if" << std::endl;
|
||||
os_ << " :: (0) -> goto " << get_state_label(s, n) << std::endl;
|
||||
fi_needed_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
state* current =it->current_state();
|
||||
if (state_is_accepting(s)
|
||||
&& it->current_condition() == bddtrue
|
||||
&& s->compare(init_) != 0
|
||||
&& s->compare(current) == 0)
|
||||
accept_all_ = n;
|
||||
else
|
||||
{
|
||||
if (fi_needed_)
|
||||
os_ << " fi;" << std::endl;
|
||||
os_ << get_state_label(s, n) << ": ";
|
||||
os_ << "/* " << automata_->format_state(s) << " */";
|
||||
os_ << std::endl;
|
||||
os_ << " if" << std::endl;
|
||||
fi_needed_ = true;
|
||||
}
|
||||
delete current;
|
||||
}
|
||||
delete it;
|
||||
}
|
||||
|
||||
void
|
||||
process_link(int in, int out, const tgba_succ_iterator* si)
|
||||
{
|
||||
if (in != accept_all_)
|
||||
{
|
||||
os_ << " :: (";
|
||||
const ltl::formula* f = bdd_to_formula(si->current_condition(),
|
||||
automata_->get_dict());
|
||||
to_spin_string(f, os_);
|
||||
destroy(f);
|
||||
state* current = si->current_state();
|
||||
os_ << ") -> goto " << get_state_label(current, out) << std::endl;
|
||||
delete current;
|
||||
}
|
||||
}
|
||||
void
|
||||
process_link(int in, int out, const tgba_succ_iterator* si)
|
||||
{
|
||||
if (in != accept_all_)
|
||||
{
|
||||
os_ << " :: (";
|
||||
const ltl::formula* f = bdd_to_formula(si->current_condition(),
|
||||
automata_->get_dict());
|
||||
to_spin_string(f, os_);
|
||||
destroy(f);
|
||||
state* current = si->current_state();
|
||||
os_ << ") -> goto " << get_state_label(current, out) << std::endl;
|
||||
delete current;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream& os_;
|
||||
const ltl::formula* f_;
|
||||
int accept_all_;
|
||||
bool fi_needed_;
|
||||
state* init_;
|
||||
};
|
||||
private:
|
||||
std::ostream& os_;
|
||||
const ltl::formula* f_;
|
||||
int accept_all_;
|
||||
bool fi_needed_;
|
||||
state* init_;
|
||||
};
|
||||
} // anonymous
|
||||
|
||||
std::ostream&
|
||||
never_claim_reachable(std::ostream& os, const tgba_tba_proxy* g,
|
||||
|
|
|
|||
|
|
@ -28,72 +28,73 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
class save_bfs : public tgba_reachable_iterator_breadth_first
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
save_bfs(const tgba* a, std::ostream& os)
|
||||
: tgba_reachable_iterator_breadth_first(a), os_(os)
|
||||
class save_bfs: public tgba_reachable_iterator_breadth_first
|
||||
{
|
||||
}
|
||||
public:
|
||||
save_bfs(const tgba* a, std::ostream& os)
|
||||
: tgba_reachable_iterator_breadth_first(a), os_(os)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
start()
|
||||
{
|
||||
os_ << "acc =";
|
||||
print_acc(automata_->all_acceptance_conditions()) << ";" << std::endl;
|
||||
}
|
||||
void
|
||||
start()
|
||||
{
|
||||
os_ << "acc =";
|
||||
print_acc(automata_->all_acceptance_conditions()) << ";" << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
process_state(const state* s, int, tgba_succ_iterator* si)
|
||||
{
|
||||
const bdd_dict* d = automata_->get_dict();
|
||||
std::string cur = automata_->format_state(s);
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
state* dest = si->current_state();
|
||||
os_ << "\"" << cur << "\", \""
|
||||
<< automata_->format_state(dest) << "\", \"";
|
||||
escape_str(os_, bdd_format_formula(d, si->current_condition()));
|
||||
os_ << "\",";
|
||||
print_acc(si->current_acceptance_conditions()) << ";" << std::endl;
|
||||
delete dest;
|
||||
}
|
||||
}
|
||||
void
|
||||
process_state(const state* s, int, tgba_succ_iterator* si)
|
||||
{
|
||||
const bdd_dict* d = automata_->get_dict();
|
||||
std::string cur = automata_->format_state(s);
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
state* dest = si->current_state();
|
||||
os_ << "\"" << cur << "\", \""
|
||||
<< automata_->format_state(dest) << "\", \"";
|
||||
escape_str(os_, bdd_format_formula(d, si->current_condition()));
|
||||
os_ << "\",";
|
||||
print_acc(si->current_acceptance_conditions()) << ";" << std::endl;
|
||||
delete dest;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream& os_;
|
||||
|
||||
std::ostream&
|
||||
print_acc(bdd acc)
|
||||
{
|
||||
const bdd_dict* d = automata_->get_dict();
|
||||
while (acc != bddfalse)
|
||||
{
|
||||
bdd cube = bdd_satone(acc);
|
||||
acc -= cube;
|
||||
while (cube != bddtrue)
|
||||
{
|
||||
assert(cube != bddfalse);
|
||||
// Display the first variable that is positive.
|
||||
// There should be only one per satisfaction.
|
||||
if (bdd_high(cube) != bddfalse)
|
||||
{
|
||||
int v = bdd_var(cube);
|
||||
bdd_dict::vf_map::const_iterator vi =
|
||||
d->acc_formula_map.find(v);
|
||||
assert(vi != d->acc_formula_map.end());
|
||||
os_ << " \"";
|
||||
escape_str(os_, ltl::to_string(vi->second)) << "\"";
|
||||
break;
|
||||
}
|
||||
cube = bdd_low(cube);
|
||||
}
|
||||
}
|
||||
return os_;
|
||||
}
|
||||
};
|
||||
private:
|
||||
std::ostream& os_;
|
||||
|
||||
std::ostream&
|
||||
print_acc(bdd acc)
|
||||
{
|
||||
const bdd_dict* d = automata_->get_dict();
|
||||
while (acc != bddfalse)
|
||||
{
|
||||
bdd cube = bdd_satone(acc);
|
||||
acc -= cube;
|
||||
while (cube != bddtrue)
|
||||
{
|
||||
assert(cube != bddfalse);
|
||||
// Display the first variable that is positive.
|
||||
// There should be only one per satisfaction.
|
||||
if (bdd_high(cube) != bddfalse)
|
||||
{
|
||||
int v = bdd_var(cube);
|
||||
bdd_dict::vf_map::const_iterator vi =
|
||||
d->acc_formula_map.find(v);
|
||||
assert(vi != d->acc_formula_map.end());
|
||||
os_ << " \"";
|
||||
escape_str(os_, ltl::to_string(vi->second)) << "\"";
|
||||
break;
|
||||
}
|
||||
cube = bdd_low(cube);
|
||||
}
|
||||
}
|
||||
return os_;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
tgba_save_reachable(std::ostream& os, const tgba* g)
|
||||
|
|
|
|||
|
|
@ -25,30 +25,32 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
class stats_bfs : public tgba_reachable_iterator_breadth_first
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
stats_bfs(const tgba* a, tgba_statistics& s)
|
||||
: tgba_reachable_iterator_breadth_first(a), s_(s)
|
||||
class stats_bfs: public tgba_reachable_iterator_breadth_first
|
||||
{
|
||||
}
|
||||
public:
|
||||
stats_bfs(const tgba* a, tgba_statistics& s)
|
||||
: tgba_reachable_iterator_breadth_first(a), s_(s)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
process_state(const state*, int, tgba_succ_iterator*)
|
||||
{
|
||||
++s_.states;
|
||||
}
|
||||
void
|
||||
process_state(const state*, int, tgba_succ_iterator*)
|
||||
{
|
||||
++s_.states;
|
||||
}
|
||||
|
||||
void
|
||||
process_link(int, int, const tgba_succ_iterator*)
|
||||
{
|
||||
++s_.transitions;
|
||||
}
|
||||
void
|
||||
process_link(int, int, const tgba_succ_iterator*)
|
||||
{
|
||||
++s_.transitions;
|
||||
}
|
||||
|
||||
private:
|
||||
tgba_statistics& s_;
|
||||
};
|
||||
private:
|
||||
tgba_statistics& s_;
|
||||
};
|
||||
} // anonymous
|
||||
|
||||
tgba_statistics
|
||||
stats_reachable(const tgba* g)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue