Add an implementation of TGTA minimization
* src/ta/taexplicit.cc, src/ta/taexplicit.hh: Bug fix TGTA * src/taalgos/minimize.cc,src/taalgos/minimize.hh: TGTA minimization * src/taalgos/tgba2ta.cc: add a TGTA minimization command (uses -Rm) * src/taalgos/minimize.cc, src/taalgos/minimize.hh (minimize_tgbta): New function. * src/taalgos/tgba2ta.cc: Set livelock-accepting flag of TGTA states to false so they can be merged with other states. * src/ta/taexplicit.cc (hash): Use id. * src/ta/taexplicit.hh: Cosmetics.
This commit is contained in:
parent
c882eadda6
commit
ed27dab306
5 changed files with 360 additions and 315 deletions
|
|
@ -266,7 +266,9 @@ namespace spot
|
||||||
size_t
|
size_t
|
||||||
state_ta_explicit::hash() const
|
state_ta_explicit::hash() const
|
||||||
{
|
{
|
||||||
return wang32_hash(tgba_state_->hash());
|
//return wang32_hash(tgba_state_->hash());
|
||||||
|
return wang32_hash(tgba_state_->hash()) ^ wang32_hash(tgba_condition_.id());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state_ta_explicit*
|
state_ta_explicit*
|
||||||
|
|
|
||||||
|
|
@ -176,11 +176,11 @@ namespace spot
|
||||||
virtual state_ta_explicit*
|
virtual state_ta_explicit*
|
||||||
clone() const;
|
clone() const;
|
||||||
|
|
||||||
virtual
|
virtual void destroy() const
|
||||||
void destroy() const
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual
|
virtual
|
||||||
~state_ta_explicit()
|
~state_ta_explicit()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
#include "ltlast/allnodes.hh"
|
#include "ltlast/allnodes.hh"
|
||||||
#include "misc/hash.hh"
|
#include "misc/hash.hh"
|
||||||
#include "misc/bddlt.hh"
|
#include "misc/bddlt.hh"
|
||||||
#include "ta/taproduct.hh"
|
#include "ta/tgbtaexplicit.hh"
|
||||||
#include "taalgos/statessetbuilder.hh"
|
#include "taalgos/statessetbuilder.hh"
|
||||||
#include "tgba/tgbaexplicit.hh"
|
#include "tgba/tgbaexplicit.hh"
|
||||||
#include "tgba/bddprint.hh"
|
#include "tgba/bddprint.hh"
|
||||||
|
|
@ -44,6 +44,7 @@ namespace spot
|
||||||
typedef Sgi::hash_set<const state*, state_ptr_hash, state_ptr_equal> hash_set;
|
typedef Sgi::hash_set<const state*, state_ptr_hash, state_ptr_equal> hash_set;
|
||||||
typedef Sgi::hash_map<const state*, unsigned, state_ptr_hash, state_ptr_equal>
|
typedef Sgi::hash_map<const state*, unsigned, state_ptr_hash, state_ptr_equal>
|
||||||
hash_map;
|
hash_map;
|
||||||
|
typedef std::list<hash_set*> partition_t;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
@ -70,13 +71,10 @@ namespace spot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// From the base automaton and the list of sets, build the minimal
|
// From the base automaton and the list of sets, build the minimal automaton
|
||||||
// tgbaulting automaton
|
void
|
||||||
ta*
|
build_result(const ta* a, std::list<hash_set*>& sets, tgba_explicit_number* result_tgba, ta_explicit* result)
|
||||||
build_result(const ta* a, std::list<hash_set*>& sets)
|
|
||||||
{
|
{
|
||||||
tgba_explicit_number* tgba = new tgba_explicit_number(a->get_dict());
|
|
||||||
ta_explicit* ta = new ta_explicit(tgba, a->all_acceptance_conditions());
|
|
||||||
|
|
||||||
// For each set, create a state in the tgbaulting automaton.
|
// 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
|
// For a state s, state_num[s] is the number of the state in the minimal
|
||||||
|
|
@ -104,7 +102,7 @@ namespace spot
|
||||||
const state* src = *hit;
|
const state* src = *hit;
|
||||||
unsigned src_num = state_num[src];
|
unsigned src_num = state_num[src];
|
||||||
|
|
||||||
state* tgba_state = tgba->add_state(src_num);
|
state* tgba_state = result_tgba->add_state(src_num);
|
||||||
bdd tgba_condition = bddtrue;
|
bdd tgba_condition = bddtrue;
|
||||||
bool is_initial_state = a->is_initial_state(src);
|
bool is_initial_state = a->is_initial_state(src);
|
||||||
if ((a->get_artificial_initial_state() == 0) && is_initial_state)
|
if ((a->get_artificial_initial_state() == 0) && is_initial_state)
|
||||||
|
|
@ -112,24 +110,24 @@ namespace spot
|
||||||
bool is_accepting_state = a->is_accepting_state(src);
|
bool is_accepting_state = a->is_accepting_state(src);
|
||||||
bool is_livelock_accepting_state = a->is_livelock_accepting_state(src);
|
bool is_livelock_accepting_state = a->is_livelock_accepting_state(src);
|
||||||
|
|
||||||
state_ta_explicit* new_src = new state_ta_explicit(tgba_state->clone(),
|
state_ta_explicit* new_src = new state_ta_explicit(tgba_state,
|
||||||
tgba_condition, is_initial_state, is_accepting_state,
|
tgba_condition, is_initial_state, is_accepting_state,
|
||||||
is_livelock_accepting_state);
|
is_livelock_accepting_state);
|
||||||
|
|
||||||
state_ta_explicit* ta_src = ta->add_state(new_src);
|
state_ta_explicit* ta_src = result->add_state(new_src);
|
||||||
|
|
||||||
if (ta_src != new_src)
|
if (ta_src != new_src)
|
||||||
{
|
{
|
||||||
new_src->destroy();
|
delete new_src;
|
||||||
}
|
}
|
||||||
else if (a->get_artificial_initial_state() != 0)
|
else if (a->get_artificial_initial_state() != 0)
|
||||||
{
|
{
|
||||||
if (a->get_artificial_initial_state() == src)
|
if (a->get_artificial_initial_state() == src)
|
||||||
ta->set_artificial_initial_state(new_src);
|
result->set_artificial_initial_state(new_src);
|
||||||
}
|
}
|
||||||
else if (is_initial_state)
|
else if (is_initial_state)
|
||||||
{
|
{
|
||||||
ta->add_to_initial_states_set(new_src);
|
result->add_to_initial_states_set(new_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
ta_succ_iterator* succit = a->succ_iter(src);
|
ta_succ_iterator* succit = a->succ_iter(src);
|
||||||
|
|
@ -142,7 +140,7 @@ namespace spot
|
||||||
if (i == state_num.end()) // Ignore useless destinations.
|
if (i == state_num.end()) // Ignore useless destinations.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
state* tgba_state = tgba->add_state(i->second);
|
state* tgba_state = result_tgba->add_state(i->second);
|
||||||
bdd tgba_condition = bddtrue;
|
bdd tgba_condition = bddtrue;
|
||||||
is_initial_state = a->is_initial_state(dst);
|
is_initial_state = a->is_initial_state(dst);
|
||||||
if ((a->get_artificial_initial_state() == 0) && is_initial_state)
|
if ((a->get_artificial_initial_state() == 0) && is_initial_state)
|
||||||
|
|
@ -151,39 +149,35 @@ namespace spot
|
||||||
bool is_livelock_accepting_state = a->is_livelock_accepting_state(
|
bool is_livelock_accepting_state = a->is_livelock_accepting_state(
|
||||||
dst);
|
dst);
|
||||||
|
|
||||||
state_ta_explicit* new_dst = new state_ta_explicit(tgba_state->clone(),
|
state_ta_explicit* new_dst = new state_ta_explicit(tgba_state,
|
||||||
tgba_condition, is_initial_state, is_accepting_state,
|
tgba_condition, is_initial_state, is_accepting_state,
|
||||||
is_livelock_accepting_state);
|
is_livelock_accepting_state);
|
||||||
|
|
||||||
state_ta_explicit* ta_dst = ta->add_state(new_dst);
|
state_ta_explicit* ta_dst = result->add_state(new_dst);
|
||||||
|
|
||||||
if (ta_dst != new_dst)
|
if (ta_dst != new_dst)
|
||||||
{
|
{
|
||||||
new_dst->destroy();
|
delete new_dst;
|
||||||
}
|
}
|
||||||
else if (a->get_artificial_initial_state() != 0)
|
else if (a->get_artificial_initial_state() != 0)
|
||||||
{
|
{
|
||||||
if (a->get_artificial_initial_state() == dst)
|
if (a->get_artificial_initial_state() == dst)
|
||||||
ta->set_artificial_initial_state(new_dst);
|
result->set_artificial_initial_state(new_dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (is_initial_state)
|
else if (is_initial_state)
|
||||||
ta->add_to_initial_states_set(new_dst);
|
result->add_to_initial_states_set(new_dst);
|
||||||
|
|
||||||
ta->create_transition(ta_src, succit->current_condition(), succit->current_acceptance_conditions(), ta_dst);
|
result->create_transition(ta_src, succit->current_condition(), succit->current_acceptance_conditions(), ta_dst);
|
||||||
|
|
||||||
}
|
}
|
||||||
delete succit;
|
delete succit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ta*
|
partition_t build_partition(const ta* ta_){
|
||||||
minimize_ta(const ta* ta_)
|
|
||||||
{
|
|
||||||
|
|
||||||
typedef std::list<hash_set*> partition_t;
|
|
||||||
partition_t cur_run;
|
partition_t cur_run;
|
||||||
partition_t next_run;
|
partition_t next_run;
|
||||||
|
|
||||||
|
|
@ -469,23 +463,67 @@ namespace spot
|
||||||
|
|
||||||
done.splice(done.end(), cur_run);
|
done.splice(done.end(), cur_run);
|
||||||
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
trace << "Final partition: ";
|
trace << "Final partition: ";
|
||||||
for (partition_t::const_iterator i = done.begin(); i != done.end(); ++i)
|
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;
|
trace << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Build the tgbault.
|
return done;
|
||||||
ta* res = build_result(ta_, done);
|
}
|
||||||
|
|
||||||
|
ta*
|
||||||
|
minimize_ta(const ta* ta_)
|
||||||
|
{
|
||||||
|
|
||||||
|
tgba_explicit_number* tgba = new tgba_explicit_number(ta_->get_dict());
|
||||||
|
|
||||||
|
ta_explicit* res = new ta_explicit(tgba, ta_->all_acceptance_conditions());
|
||||||
|
|
||||||
|
|
||||||
|
partition_t partition = build_partition(ta_);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Build the ta automata result.
|
||||||
|
build_result(ta_, partition, tgba, res);
|
||||||
|
|
||||||
// Free all the allocated memory.
|
// Free all the allocated memory.
|
||||||
std::list<hash_set*>::iterator itdone;
|
std::list<hash_set*>::iterator itdone;
|
||||||
for (itdone = done.begin(); itdone != done.end(); ++itdone)
|
for (itdone = partition.begin(); itdone != partition.end(); ++itdone)
|
||||||
delete *itdone;
|
delete *itdone;
|
||||||
//delete ta_;
|
//delete ta_;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tgbta*
|
||||||
|
minimize_tgbta(const tgbta* tgbta_)
|
||||||
|
{
|
||||||
|
|
||||||
|
tgba_explicit_number* tgba = new tgba_explicit_number(tgbta_->get_dict());
|
||||||
|
|
||||||
|
tgbta_explicit* res = new tgbta_explicit(tgba, tgbta_->all_acceptance_conditions(),0);
|
||||||
|
|
||||||
|
const ta_explicit* tgbta = dynamic_cast <const tgbta_explicit*> (tgbta_);
|
||||||
|
|
||||||
|
partition_t partition = build_partition(tgbta);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Build the tgbault.
|
||||||
|
build_result(tgbta, partition,tgba, res);
|
||||||
|
|
||||||
|
// Free all the allocated memory.
|
||||||
|
std::list<hash_set*>::iterator itdone;
|
||||||
|
for (itdone = partition.begin(); itdone != partition.end(); ++itdone)
|
||||||
|
delete *itdone;
|
||||||
|
//delete ta_;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
# define SPOT_TAALGOS_MINIMIZE_HH
|
# define SPOT_TAALGOS_MINIMIZE_HH
|
||||||
|
|
||||||
# include "ta/ta.hh"
|
# include "ta/ta.hh"
|
||||||
|
# include "ta/tgbta.hh"
|
||||||
# include "ta/taexplicit.hh"
|
# include "ta/taexplicit.hh"
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
|
|
@ -30,6 +31,9 @@ namespace spot
|
||||||
ta*
|
ta*
|
||||||
minimize_ta(const ta* ta_);
|
minimize_ta(const ta* ta_);
|
||||||
|
|
||||||
|
tgbta*
|
||||||
|
minimize_tgbta(const tgbta* tgbta_);
|
||||||
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -586,8 +586,9 @@ namespace spot
|
||||||
<< "***tgba_to_tgbta: POST if (state->is_livelock_accepting_state()) ... create_transition ***"
|
<< "***tgba_to_tgbta: POST if (state->is_livelock_accepting_state()) ... create_transition ***"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
state->set_livelock_accepting_state(false);
|
||||||
}
|
}
|
||||||
//state->set_livelock_accepting_state(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->compare(tgbta->get_artificial_initial_state()))
|
if (state->compare(tgbta->get_artificial_initial_state()))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue