Make sure we can multiply two tgba_explicit.

* tgba/state.hh (state::translate, state::clone, state::as_bdd):
New virtual methods.
* tgba/stataebdd.cc (state::translate, state::clone): New methods.
* tgba/stataebdd.hh (state::translate, state::clone): New methods.
* tgba/tgbabddprod.cc (state_bdd_product::clone,
tgba_bdd_product_succ_iterator::~tgba_bdd_product_succ_iterator):
New methods.
(tgba_bdd_product_succ_iterator::first): Reset right_
if any of left_ or right_ is already done (i.e., is empty).
(tgba_bdd_product_succ_iterator::done): Return true
if right_ is NULL.
(tgba_bdd_product_succ_iterator::current_state,
tgba_bdd_product::get_init_state): Work	directory with `state's.
* tgba/tgbabddprod.hh (state_bdd_product::clone,
tgba_bdd_product_succ_iterator::~tgba_bdd_product_succ_iterator):
New methods.
* tgba/tgbabddtranslateproxy.cc
(tgba_bdd_translate_proxy_succ_iterator::
tgba_bdd_translate_proxy_succ_iterator): Work on any kind of iteraator.
(tgba_bdd_translate_proxy_succ_iterator::
~tgba_bdd_translate_proxy_succ_iterator): New method.
(tgba_bdd_translate_proxy_succ_iterator::current_state,
tgba_bdd_translate_proxy::get_init_state,
tgba_bdd_translate_proxy::succ_iter): Work on `state's and
`tgba_succ_iterator's directlry.
(tgba_bdd_translate_proxy::format_state): Delegate formating
to the proxied automata.
* tgba/tgbaexplicit.cc (state_explicit::clone): New method.
* src/tgba/tgbaexplicit.cc (tgba_explicit::get_condition,
tgba_explicit::get_promise): Call ltl::destroy on existing formulae.
* tgbatest/Makefile.am (check_PROGRAMS): Add explprod.
(explprod_SOURCES): New variable.
(TESTS): Add explprod.test.
(CLEANFILES): Add input1 and input2.
This commit is contained in:
Alexandre Duret-Lutz 2003-06-16 15:18:20 +00:00
parent 5d2e0a4224
commit ab09c18597
16 changed files with 275 additions and 85 deletions

View file

@ -1,3 +1,42 @@
2003-06-16 Alexandre Duret-Lutz <aduret@src.lip6.fr>
Make sure we can multiply two tgba_explicit.
* tgba/state.hh (state::translate, state::clone, state::as_bdd):
New virtual methods.
* tgba/stataebdd.cc (state::translate, state::clone): New methods.
* tgba/stataebdd.hh (state::translate, state::clone): New methods.
* tgba/tgbabddprod.cc (state_bdd_product::clone,
tgba_bdd_product_succ_iterator::~tgba_bdd_product_succ_iterator):
New methods.
(tgba_bdd_product_succ_iterator::first): Reset right_
if any of left_ or right_ is already done (i.e., is empty).
(tgba_bdd_product_succ_iterator::done): Return true
if right_ is NULL.
(tgba_bdd_product_succ_iterator::current_state,
tgba_bdd_product::get_init_state): Work directory with `state's.
* tgba/tgbabddprod.hh (state_bdd_product::clone,
tgba_bdd_product_succ_iterator::~tgba_bdd_product_succ_iterator):
New methods.
* tgba/tgbabddtranslateproxy.cc
(tgba_bdd_translate_proxy_succ_iterator::
tgba_bdd_translate_proxy_succ_iterator): Work on any kind of iteraator.
(tgba_bdd_translate_proxy_succ_iterator::
~tgba_bdd_translate_proxy_succ_iterator): New method.
(tgba_bdd_translate_proxy_succ_iterator::current_state,
tgba_bdd_translate_proxy::get_init_state,
tgba_bdd_translate_proxy::succ_iter): Work on `state's and
`tgba_succ_iterator's directlry.
(tgba_bdd_translate_proxy::format_state): Delegate formating
to the proxied automata.
* tgba/tgbaexplicit.cc (state_explicit::clone): New method.
* src/tgba/tgbaexplicit.cc (tgba_explicit::get_condition,
tgba_explicit::get_promise): Call ltl::destroy on existing formulae.
* tgbatest/Makefile.am (check_PROGRAMS): Add explprod.
(explprod_SOURCES): New variable.
(TESTS): Add explprod.test.
(CLEANFILES): Add input1 and input2.
2003-06-12 Alexandre Duret-Lutz <aduret@src.lip6.fr> 2003-06-12 Alexandre Duret-Lutz <aduret@src.lip6.fr>
* src/tgba/tgbabddconcrete.cc (set_init_state, succ_iter): Make * src/tgba/tgbabddconcrete.cc (set_init_state, succ_iter): Make

View file

@ -22,6 +22,28 @@ namespace spot
/// \sa spot::state_ptr_less_than /// \sa spot::state_ptr_less_than
virtual int compare(const state* other) const = 0; virtual int compare(const state* other) const = 0;
/// \brief Translate a state.
///
/// If this state uses any BDD variable. This function
/// should rewrite the variables according to \a rewrite.
/// This used by spot::tgbabddtranslateproxy.
virtual void translate(bddPair* rewrite)
{
// This does nothing by default and is
// overridden in spot::state_bdd.
(void) rewrite;
}
/// Duplicate a state.
virtual state* clone() const = 0;
/// Return the BDD part of the state.
virtual bdd
as_bdd() const
{
return bddtrue;
}
virtual ~state() virtual ~state()
{ {
} }

View file

@ -1,9 +1,10 @@
#include "statebdd.hh" #include "statebdd.hh"
#include "bddprint.hh" #include <bdd.h>
#include <cassert> #include <cassert>
namespace spot namespace spot
{ {
int int
state_bdd::compare(const state* other) const state_bdd::compare(const state* other) const
{ {
@ -14,4 +15,18 @@ namespace spot
assert(o); assert(o);
return o->as_bdd().id() - state_.id(); return o->as_bdd().id() - state_.id();
} }
void
state_bdd::translate(bddPair* rewrite)
{
state_ = bdd_replace(state_, rewrite);
}
/// Duplicate a state.
state_bdd*
state_bdd::clone() const
{
return new state_bdd(*this);
}
} }

View file

@ -16,20 +16,15 @@ namespace spot
} }
/// Return the BDD part of the state. /// Return the BDD part of the state.
bdd virtual bdd
as_bdd() const as_bdd() const
{ {
return state_; return state_;
} }
/// Return the BDD part of the state.
bdd&
as_bdd()
{
return state_;
}
virtual int compare(const state* other) const; virtual int compare(const state* other) const;
virtual void translate(bddPair* rewrite);
virtual state_bdd* clone() const;
protected: protected:
bdd state_; ///< BDD representation of the state. bdd state_; ///< BDD representation of the state.

View file

@ -26,6 +26,12 @@ namespace spot
return right_->compare(o->right()); return right_->compare(o->right());
} }
state_bdd_product*
state_bdd_product::clone() const
{
return new state_bdd_product(*this);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// tgba_bdd_product_succ_iterator // tgba_bdd_product_succ_iterator
@ -35,6 +41,13 @@ namespace spot
{ {
} }
tgba_bdd_product_succ_iterator::~tgba_bdd_product_succ_iterator()
{
delete left_;
if (right_)
delete right_;
}
void void
tgba_bdd_product_succ_iterator::step_() tgba_bdd_product_succ_iterator::step_()
{ {
@ -67,8 +80,20 @@ namespace spot
void void
tgba_bdd_product_succ_iterator::first() tgba_bdd_product_succ_iterator::first()
{ {
if (!right_)
return;
left_->first(); left_->first();
right_->first(); right_->first();
// If one of the two successor set 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_->done() || right_->done())
{
delete right_;
right_ = 0;
}
next_non_false_(); next_non_false_();
} }
@ -82,18 +107,15 @@ namespace spot
bool bool
tgba_bdd_product_succ_iterator::done() tgba_bdd_product_succ_iterator::done()
{ {
return right_->done(); return !right_ || right_->done();
} }
state_bdd* state_bdd_product*
tgba_bdd_product_succ_iterator::current_state() tgba_bdd_product_succ_iterator::current_state()
{ {
state_bdd* ls = dynamic_cast<state_bdd*>(left_->current_state()); return new state_bdd_product(left_->current_state(),
state_bdd* rs = dynamic_cast<state_bdd*>(right_->current_state()); right_->current_state());
assert(ls);
assert(rs);
return new state_bdd_product(ls, rs);
} }
bdd bdd
@ -149,11 +171,8 @@ namespace spot
state* state*
tgba_bdd_product::get_init_state() const tgba_bdd_product::get_init_state() const
{ {
state_bdd* ls = dynamic_cast<state_bdd*>(left_->get_init_state()); return new state_bdd_product(left_->get_init_state(),
state_bdd* rs = dynamic_cast<state_bdd*>(right_->get_init_state()); right_->get_init_state());
assert(ls);
assert(rs);
return new state_bdd_product(ls, rs);
} }
tgba_bdd_product_succ_iterator* tgba_bdd_product_succ_iterator*

View file

@ -19,7 +19,7 @@ namespace spot
/// \param right The state from the right automaton. /// \param right The state from the right automaton.
/// These state are acquired by spot::state_bdd_product, and will /// These state are acquired by spot::state_bdd_product, and will
/// be deleted on destruction. /// be deleted on destruction.
state_bdd_product(state_bdd* left, state_bdd* right) state_bdd_product(state* left, state* right)
: state_bdd(left->as_bdd() & right->as_bdd()), : state_bdd(left->as_bdd() & right->as_bdd()),
left_(left), left_(left),
right_(right) right_(right)
@ -28,23 +28,24 @@ namespace spot
virtual ~state_bdd_product(); virtual ~state_bdd_product();
state_bdd* state*
left() const left() const
{ {
return left_; return left_;
} }
state_bdd* state*
right() const right() const
{ {
return right_; return right_;
} }
virtual int compare(const state* other) const; virtual int compare(const state* other) const;
virtual state_bdd_product* clone() const;
private: private:
state_bdd* left_; ///< State from the left automaton. state* left_; ///< State from the left automaton.
state_bdd* right_; ///< State from the right automaton. state* right_; ///< State from the right automaton.
}; };
@ -55,13 +56,15 @@ namespace spot
tgba_bdd_product_succ_iterator(tgba_succ_iterator* left, tgba_bdd_product_succ_iterator(tgba_succ_iterator* left,
tgba_succ_iterator* right); tgba_succ_iterator* right);
virtual ~tgba_bdd_product_succ_iterator();
// iteration // iteration
void first(); void first();
void next(); void next();
bool done(); bool done();
// inspection // inspection
state_bdd* current_state(); state_bdd_product* current_state();
bdd current_condition(); bdd current_condition();
bdd current_promise(); bdd current_promise();

View file

@ -9,12 +9,18 @@ namespace spot
// -------------------------------------- // --------------------------------------
tgba_bdd_translate_proxy_succ_iterator:: tgba_bdd_translate_proxy_succ_iterator::
tgba_bdd_translate_proxy_succ_iterator(tgba_succ_iterator_concrete* it, tgba_bdd_translate_proxy_succ_iterator(tgba_succ_iterator* it,
bddPair* rewrite) bddPair* rewrite)
: iter_(it), rewrite_(rewrite) : iter_(it), rewrite_(rewrite)
{ {
} }
tgba_bdd_translate_proxy_succ_iterator::
~tgba_bdd_translate_proxy_succ_iterator()
{
delete iter_;
}
void void
tgba_bdd_translate_proxy_succ_iterator::first() tgba_bdd_translate_proxy_succ_iterator::first()
{ {
@ -33,11 +39,11 @@ namespace spot
return iter_->done(); return iter_->done();
} }
state_bdd* state*
tgba_bdd_translate_proxy_succ_iterator::current_state() tgba_bdd_translate_proxy_succ_iterator::current_state()
{ {
state_bdd* s = iter_->current_state(); state* s = iter_->current_state();
s->as_bdd() = bdd_replace(s->as_bdd(), rewrite_); s->translate(rewrite_);
return s; return s;
} }
@ -99,25 +105,24 @@ namespace spot
bdd_freepair(rewrite_to_); bdd_freepair(rewrite_to_);
} }
state_bdd* state*
tgba_bdd_translate_proxy::get_init_state() const tgba_bdd_translate_proxy::get_init_state() const
{ {
state_bdd* s = dynamic_cast<state_bdd*>(from_.get_init_state()); state* s = from_.get_init_state();
assert(s); s->translate(rewrite_to_);
s->as_bdd() = bdd_replace(s->as_bdd(), rewrite_to_);
return s; return s;
} }
tgba_bdd_translate_proxy_succ_iterator* tgba_bdd_translate_proxy_succ_iterator*
tgba_bdd_translate_proxy::succ_iter(const state* state) const tgba_bdd_translate_proxy::succ_iter(const state* s) const
{ {
const state_bdd* s = dynamic_cast<const state_bdd*>(state); state* s2 = s->clone();
assert(s); s2->translate(rewrite_from_);
state_bdd s2(bdd_replace(s->as_bdd(), rewrite_from_)); tgba_bdd_translate_proxy_succ_iterator *res =
tgba_succ_iterator_concrete* it = new tgba_bdd_translate_proxy_succ_iterator(from_.succ_iter(s2),
dynamic_cast<tgba_succ_iterator_concrete*>(from_.succ_iter(&s2)); rewrite_to_);
assert(it); delete s2;
return new tgba_bdd_translate_proxy_succ_iterator(it, rewrite_to_); return res;
} }
const tgba_bdd_dict& const tgba_bdd_dict&
@ -127,12 +132,13 @@ namespace spot
} }
std::string std::string
tgba_bdd_translate_proxy::format_state(const state* state) const tgba_bdd_translate_proxy::format_state(const state* s) const
{ {
const state_bdd* s = dynamic_cast<const state_bdd*>(state); state* s2 = s->clone();
assert(s); s2->translate(rewrite_from_);
return bdd_format_set(to_, s->as_bdd()); std::string res = from_.format_state(s2);
delete s2;
return res;
} }
} }

View file

@ -2,7 +2,6 @@
# define SPOT_TGBA_TGBABDDTRANSLATEPROXY_HH # define SPOT_TGBA_TGBABDDTRANSLATEPROXY_HH
#include "tgba.hh" #include "tgba.hh"
#include "succiterconcrete.hh"
namespace spot namespace spot
{ {
@ -11,8 +10,9 @@ namespace spot
class tgba_bdd_translate_proxy_succ_iterator: public tgba_succ_iterator class tgba_bdd_translate_proxy_succ_iterator: public tgba_succ_iterator
{ {
public: public:
tgba_bdd_translate_proxy_succ_iterator tgba_bdd_translate_proxy_succ_iterator(tgba_succ_iterator* it,
(tgba_succ_iterator_concrete* it, bddPair* rewrite); bddPair* rewrite);
virtual ~tgba_bdd_translate_proxy_succ_iterator();
// iteration // iteration
void first(); void first();
@ -20,11 +20,11 @@ namespace spot
bool done(); bool done();
// inspection // inspection
state_bdd* current_state(); state* current_state();
bdd current_condition(); bdd current_condition();
bdd current_promise(); bdd current_promise();
protected: protected:
tgba_succ_iterator_concrete* iter_; tgba_succ_iterator* iter_;
bddPair* rewrite_; bddPair* rewrite_;
}; };
@ -42,7 +42,7 @@ namespace spot
virtual ~tgba_bdd_translate_proxy(); virtual ~tgba_bdd_translate_proxy();
virtual state_bdd* get_init_state() const; virtual state* get_init_state() const;
virtual tgba_bdd_translate_proxy_succ_iterator* virtual tgba_bdd_translate_proxy_succ_iterator*
succ_iter(const state* state) const; succ_iter(const state* state) const;

View file

@ -1,4 +1,5 @@
#include "ltlast/atomic_prop.hh" #include "ltlast/atomic_prop.hh"
#include "ltlvisit/destroy.hh"
#include "tgbaexplicit.hh" #include "tgbaexplicit.hh"
#include <cassert> #include <cassert>
@ -68,6 +69,12 @@ namespace spot
return o->get_state() - get_state(); return o->get_state() - get_state();
} }
state_explicit*
state_explicit::clone() const
{
return new state_explicit(*this);
}
//////////////////////////////////////// ////////////////////////////////////////
// tgba_explicit // tgba_explicit
@ -135,6 +142,7 @@ namespace spot
} }
else else
{ {
ltl::destroy(f);
v = i->second; v = i->second;
} }
return v; return v;
@ -162,6 +170,7 @@ namespace spot
} }
else else
{ {
ltl::destroy(f);
v = i->second; v = i->second;
} }
return v; return v;

View file

@ -68,6 +68,8 @@ namespace spot
virtual int compare(const spot::state* other) const; virtual int compare(const spot::state* other) const;
virtual state_explicit* clone() const;
virtual ~state_explicit() virtual ~state_explicit()
{ {
} }

View file

@ -9,11 +9,13 @@ check_PROGRAMS = \
tgbaread \ tgbaread \
ltl2tgba \ ltl2tgba \
ltlprod \ ltlprod \
bddprod bddprod \
explprod
bddprod_SOURCES = ltlprod.cc bddprod_SOURCES = ltlprod.cc
bddprod_CXXFLAGS = -DBDD_CONCRETE_PRODUCT bddprod_CXXFLAGS = -DBDD_CONCRETE_PRODUCT
explicit_SOURCES = explicit.cc explicit_SOURCES = explicit.cc
explprod_SOURCES = explprod.cc
ltl2tgba_SOURCES = ltl2tgba.cc ltl2tgba_SOURCES = ltl2tgba.cc
ltlprod_SOURCES = ltlprod.cc ltlprod_SOURCES = ltlprod.cc
readsave_SOURCES = readsave.cc readsave_SOURCES = readsave.cc
@ -25,8 +27,9 @@ TESTS = \
readsave.test \ readsave.test \
ltl2tgba.test \ ltl2tgba.test \
ltlprod.test \ ltlprod.test \
bddprod.test bddprod.test \
explprod.test
EXTRA_DIST = $(TESTS) EXTRA_DIST = $(TESTS)
CLEANFILES = input stdout expected CLEANFILES = input input1 input2 stdout expected

48
src/tgbatest/explprod.cc Normal file
View file

@ -0,0 +1,48 @@
#include <iostream>
#include <cassert>
#include "tgba/ltl2tgba.hh"
#include "tgba/tgbaexplicit.hh"
#include "tgba/tgbabddprod.hh"
#include "tgbaparse/public.hh"
#include "tgbaalgos/save.hh"
#include "ltlast/allnodes.hh"
void
syntax(char* prog)
{
std::cerr << prog << " file1 file2" << std::endl;
exit(2);
}
int
main(int argc, char** argv)
{
int exit_code = 0;
if (argc != 3)
syntax(argv[0]);
spot::ltl::environment& env(spot::ltl::default_environment::instance());
spot::tgba_parse_error_list pel1;
spot::tgba_explicit* a1 = spot::tgba_parse(argv[1], pel1, env);
if (spot::format_tgba_parse_errors(std::cerr, pel1))
return 2;
spot::tgba_parse_error_list pel2;
spot::tgba_explicit* a2 = spot::tgba_parse(argv[2], pel2, env);
if (spot::format_tgba_parse_errors(std::cerr, pel1))
return 2;
{
spot::tgba_bdd_product p(*a1, *a2);
spot::tgba_save_reachable(std::cout, p);
}
assert(spot::ltl::unop::instance_count() == 0);
assert(spot::ltl::binop::instance_count() == 0);
assert(spot::ltl::multop::instance_count() == 0);
assert(spot::ltl::atomic_prop::instance_count() != 0);
delete a1;
delete a2;
assert(spot::ltl::atomic_prop::instance_count() == 0);
return exit_code;
}

29
src/tgbatest/explprod.test Executable file
View file

@ -0,0 +1,29 @@
#!/bin/sh
. ./defs
set -e
cat >input1 <<EOF
s1, s3, a,;
s1, s2, b, p1;
s2, s1, !a,;
s2, s3, c,;
EOF
cat >input2 <<EOF
s1, s2, b, p2;
s2, s1, a, p3;
EOF
cat >expected <<EOF
"s1 * s1", "s3 * s2", a b, p2;
"s1 * s1", "s2 * s2", b, p2 p1;
"s2 * s2", "s3 * s1", c a, p3;
EOF
./explprod input1 input2 > stdout
cat stdout
diff stdout expected
rm input1 input2 stdout expected