* src/tgbatest/ltl2tgba.cc: Add some option for the reduction of
automata. * src/tgbatest/spotlbtt.test, src/tgbatest/Makefile.am: Add some test for reduction of automata. * src/tgbaalgos/reductgba_sim_del.cc, src/tgbaalgos/reductgba_sim.cc, src/tgbaalgos/reductgba_sim.hh: Compute some simulation relation to reduce a tgba. * src/tgba/tgbareduc.cc, src/tgba/tgbareduc.hh: A implementation of tgba for the reduction. * src/tgbaalgos/Makefile.am, src/tgba/Makefile.am: Add the reduction of automata. * src/ltlvisit/syntimpl.cc, src/ltlvisit/basereduc.cc: Lot of mistake are corrected. * src/ltlvisit/syntimpl.hh, src/ltlvisit/reducform.cc, src/ltlvisit/reducform.hh, src/ltltest/reduc.cc: Adjust. * src/ltltest/equals.cc, src/ltltest/reduccmp.test, src/ltltest/Makefile.am: Add a test for reduction.
This commit is contained in:
parent
383f7e170a
commit
8d3606ff07
20 changed files with 3155 additions and 133 deletions
|
|
@ -37,7 +37,8 @@ tgbaalgos_HEADERS = \
|
|||
powerset.hh \
|
||||
reachiter.hh \
|
||||
save.hh \
|
||||
stats.hh
|
||||
stats.hh \
|
||||
reductgba_sim.hh
|
||||
|
||||
noinst_LTLIBRARIES = libtgbaalgos.la
|
||||
libtgbaalgos_la_SOURCES = \
|
||||
|
|
@ -51,6 +52,8 @@ libtgbaalgos_la_SOURCES = \
|
|||
powerset.cc \
|
||||
reachiter.cc \
|
||||
save.cc \
|
||||
stats.cc
|
||||
stats.cc \
|
||||
reductgba_sim.cc \
|
||||
reductgba_sim_del.cc
|
||||
|
||||
libtgbaalgos_la_LIBADD = gtec/libgtec.la
|
||||
|
|
|
|||
655
src/tgbaalgos/reductgba_sim.cc
Normal file
655
src/tgbaalgos/reductgba_sim.cc
Normal file
|
|
@ -0,0 +1,655 @@
|
|||
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Spot; see the file COPYING. If not, write to the Free
|
||||
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
|
||||
#include "reductgba_sim.hh"
|
||||
#include "tgba/bddprint.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// spoiler_node
|
||||
|
||||
spoiler_node::spoiler_node(const state* d_node,
|
||||
const state* s_node,
|
||||
int num)
|
||||
{
|
||||
num_ = num;
|
||||
sc_ = new state_couple(d_node, s_node);
|
||||
//lnode_succ = new Sgi::vector<spoiler_node*>;
|
||||
lnode_succ = new sn_v;
|
||||
lnode_pred = new sn_v;
|
||||
this->not_win = false;
|
||||
}
|
||||
|
||||
spoiler_node::~spoiler_node()
|
||||
{
|
||||
lnode_succ->clear();
|
||||
lnode_pred->clear();
|
||||
delete lnode_succ;
|
||||
delete lnode_pred;
|
||||
delete sc_;
|
||||
}
|
||||
|
||||
void
|
||||
spoiler_node::add_succ(spoiler_node* n)
|
||||
{
|
||||
lnode_succ->push_back(n);
|
||||
}
|
||||
|
||||
void
|
||||
spoiler_node::del_succ(spoiler_node* n)
|
||||
{
|
||||
//std::cout << "del_succ : begin" << std::endl;
|
||||
for (sn_v::iterator i = lnode_succ->begin();
|
||||
i != lnode_succ->end();)
|
||||
{
|
||||
if (*i == n)
|
||||
{
|
||||
//std::cout << "erase" << std::endl;
|
||||
i = lnode_succ->erase(i);
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
//std::cout << "del_succ : end" << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
spoiler_node::add_pred(spoiler_node* n)
|
||||
{
|
||||
lnode_pred->push_back(n);
|
||||
}
|
||||
|
||||
void
|
||||
spoiler_node::del_pred()
|
||||
{
|
||||
for (sn_v::iterator i = lnode_pred->begin();
|
||||
i != lnode_pred->end(); ++i)
|
||||
(*i)->del_succ(this);
|
||||
}
|
||||
|
||||
bool
|
||||
spoiler_node::set_win()
|
||||
{
|
||||
bool change = not_win;
|
||||
for (Sgi::vector<spoiler_node*>::iterator i = lnode_succ->begin();
|
||||
i != lnode_succ->end(); ++i)
|
||||
{
|
||||
not_win |= (*i)->not_win;
|
||||
}
|
||||
return (change != not_win);
|
||||
}
|
||||
|
||||
std::string
|
||||
spoiler_node::to_string(const tgba* a)
|
||||
{
|
||||
std::ostringstream os;
|
||||
// print the node.
|
||||
os << num_
|
||||
<< " [shape=box, label=\"("
|
||||
<< a->format_state(sc_->first)
|
||||
<< ", "
|
||||
<< a->format_state(sc_->second)
|
||||
<< ")\"]"
|
||||
<< std::endl;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
spoiler_node::succ_to_string()
|
||||
{
|
||||
std::ostringstream os;
|
||||
sn_v::iterator i;
|
||||
for (i = lnode_succ->begin(); i != lnode_succ->end(); ++i)
|
||||
{
|
||||
os << num_ << " -> " << (*i)->num_ << std::endl;
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
int
|
||||
spoiler_node::get_nb_succ()
|
||||
{
|
||||
return lnode_succ->size();
|
||||
}
|
||||
|
||||
const state*
|
||||
spoiler_node::get_spoiler_node()
|
||||
{
|
||||
return sc_->first;
|
||||
}
|
||||
|
||||
const state*
|
||||
spoiler_node::get_duplicator_node()
|
||||
{
|
||||
return sc_->second;
|
||||
}
|
||||
|
||||
state_couple*
|
||||
spoiler_node::get_pair()
|
||||
{
|
||||
return sc_;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// duplicator_node
|
||||
|
||||
duplicator_node::duplicator_node(const state* d_node,
|
||||
const state* s_node,
|
||||
bdd l,
|
||||
bdd a,
|
||||
int num)
|
||||
: spoiler_node(d_node, s_node, num),
|
||||
label_(l),
|
||||
acc_(a)
|
||||
{
|
||||
}
|
||||
|
||||
duplicator_node::~duplicator_node()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
duplicator_node::set_win()
|
||||
{
|
||||
bool change = not_win;
|
||||
|
||||
if (!this->get_nb_succ())
|
||||
not_win = true;
|
||||
else
|
||||
{
|
||||
not_win = true;
|
||||
for (Sgi::vector<spoiler_node*>::iterator i = lnode_succ->begin();
|
||||
i != lnode_succ->end(); ++i)
|
||||
{
|
||||
not_win &= (*i)->not_win;
|
||||
}
|
||||
}
|
||||
return (change != not_win);
|
||||
}
|
||||
|
||||
std::string
|
||||
duplicator_node::to_string(const tgba* a)
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
||||
// print the node.
|
||||
os << num_
|
||||
<< " [shape=box, label=\"("
|
||||
<< a->format_state(sc_->first)
|
||||
<< ", "
|
||||
<< a->format_state(sc_->second)
|
||||
<< ", ";
|
||||
bdd_print_acc(os, a->get_dict(), acc_);
|
||||
os << ")\"]"
|
||||
<< std::endl;
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
bool
|
||||
duplicator_node::match(bdd l, bdd a)
|
||||
{
|
||||
return ((l == label_) && (a == acc_));
|
||||
}
|
||||
|
||||
bool
|
||||
duplicator_node::implies(bdd l, bdd a)
|
||||
{
|
||||
// if (a | !b) == true then (a => b).
|
||||
return (((l | !label_) == bddtrue) &&
|
||||
((a | !acc_) == bddtrue));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// parity_game_graph
|
||||
|
||||
void
|
||||
parity_game_graph::start()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph::end()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph::process_state(const state* s,
|
||||
int ,
|
||||
tgba_succ_iterator*)
|
||||
{
|
||||
tgba_state_.push_back(s);
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph::process_link(int ,
|
||||
int ,
|
||||
const tgba_succ_iterator*)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph::print(std::ostream& os)
|
||||
{
|
||||
Sgi::vector<spoiler_node*>::iterator i1;
|
||||
Sgi::vector<duplicator_node*>::iterator i2;
|
||||
|
||||
int n = 0;
|
||||
|
||||
os << "digraph G {" << std::endl;
|
||||
|
||||
os << "{" << std::endl
|
||||
<< "rank = same;" << std::endl
|
||||
<< "node [color=red];" << std::endl;
|
||||
for (i1 = spoiler_vertice_.begin();
|
||||
i1 != spoiler_vertice_.end(); ++i1)
|
||||
{
|
||||
os << (*i1)->to_string(automata_);
|
||||
n++;
|
||||
if (n > 20)
|
||||
{
|
||||
n = 0;
|
||||
os << "}" << std::endl << std::endl
|
||||
<< "{" << std::endl
|
||||
<< "rank = same" << std::endl
|
||||
<< "node [color=red];" << std::endl;
|
||||
}
|
||||
}
|
||||
os << "}" << std::endl;
|
||||
|
||||
n = 0;
|
||||
os << "{" << std::endl
|
||||
<< "rank = same;" << std::endl
|
||||
<< "node [color=green];" << std::endl;
|
||||
for (i2 = duplicator_vertice_.begin();
|
||||
i2 != duplicator_vertice_.end(); ++i2)
|
||||
{
|
||||
os << (*i2)->to_string(automata_);
|
||||
n++;
|
||||
if (n > 20)
|
||||
{
|
||||
n = 0;
|
||||
os << "}" << std::endl << std::endl
|
||||
<< "{" << std::endl
|
||||
<< "rank = same" << std::endl
|
||||
<< "node [color=green];" << std::endl;
|
||||
}
|
||||
}
|
||||
os << "}" << std::endl << std::endl;
|
||||
|
||||
os << "edge [color=red];" << std::endl;
|
||||
for (i1 = spoiler_vertice_.begin();
|
||||
i1 != spoiler_vertice_.end(); ++i1)
|
||||
{
|
||||
os << (*i1)->succ_to_string();
|
||||
}
|
||||
|
||||
os << std::endl
|
||||
<< "edge [color=green];" << std::endl;
|
||||
for (i2 = duplicator_vertice_.begin();
|
||||
i2 != duplicator_vertice_.end(); ++i2)
|
||||
{
|
||||
os << (*i2)->succ_to_string();
|
||||
}
|
||||
|
||||
os << "}" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
parity_game_graph::~parity_game_graph()
|
||||
{
|
||||
Sgi::vector<spoiler_node*>::iterator i1;
|
||||
Sgi::vector<duplicator_node*>::iterator i2;
|
||||
|
||||
for (i1 = spoiler_vertice_.begin();
|
||||
i1 != spoiler_vertice_.end(); ++i1)
|
||||
{
|
||||
delete *i1;
|
||||
}
|
||||
|
||||
for (i2 = duplicator_vertice_.begin();
|
||||
i2 != duplicator_vertice_.end(); ++i2)
|
||||
{
|
||||
delete *i2;
|
||||
}
|
||||
|
||||
spoiler_vertice_.clear();
|
||||
duplicator_vertice_.clear();
|
||||
}
|
||||
|
||||
parity_game_graph::parity_game_graph(const tgba* a)
|
||||
: tgba_reachable_iterator_breadth_first(a)
|
||||
{
|
||||
this->run();
|
||||
nb_node_parity_game = 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// parity_game_graph_direct
|
||||
|
||||
void
|
||||
parity_game_graph_direct::build_couple()
|
||||
{
|
||||
tgba_succ_iterator* si = NULL;
|
||||
typedef Sgi::pair<bdd, bdd> couple_bdd;
|
||||
couple_bdd *p = NULL;
|
||||
Sgi::vector<couple_bdd*>* trans = NULL;
|
||||
bool exist = false;
|
||||
spot::state* s = NULL;
|
||||
|
||||
for (Sgi::vector<const state*>::iterator i = tgba_state_.begin();
|
||||
i != tgba_state_.end(); ++i)
|
||||
{
|
||||
|
||||
// spoiler node are all state couple (i,j)
|
||||
for (Sgi::vector<const state*>::iterator j = tgba_state_.begin();
|
||||
j != tgba_state_.end(); ++j)
|
||||
{
|
||||
spoiler_node* n1 = new spoiler_node(*i,
|
||||
*j,
|
||||
nb_node_parity_game++);
|
||||
spoiler_vertice_.push_back(n1);
|
||||
}
|
||||
|
||||
// duplicator node are all state couple where
|
||||
// the first state i are reachable.
|
||||
trans = new Sgi::vector<couple_bdd*>;
|
||||
for (Sgi::vector<const state*>::iterator j = tgba_state_.begin();
|
||||
j != tgba_state_.end(); ++j)
|
||||
{
|
||||
si = automata_->succ_iter(*j);
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
|
||||
// if there exist a predecessor of i named j
|
||||
s = si->current_state();
|
||||
if (s->compare(*i) == 0)
|
||||
{
|
||||
|
||||
// p is the label of the transition j->i
|
||||
p = new couple_bdd(si->current_condition(),
|
||||
si->current_acceptance_conditions());
|
||||
|
||||
// If an other predecessor of i has the same label p
|
||||
// to reach i, then we don't compute the duplicator node.
|
||||
exist = false;
|
||||
for (Sgi::vector<couple_bdd*>::iterator v
|
||||
= trans->begin();
|
||||
v != trans->end(); ++v)
|
||||
{
|
||||
if ((si->current_condition() == (*v)->first) &&
|
||||
(si->current_acceptance_conditions()
|
||||
== (*v)->second))
|
||||
exist = true;
|
||||
}
|
||||
|
||||
if (!exist)
|
||||
{
|
||||
// We build all the state couple with the label p.
|
||||
trans->push_back(p);
|
||||
for (Sgi::vector<const state*>::iterator s
|
||||
= tgba_state_.begin();
|
||||
s != tgba_state_.end(); ++s)
|
||||
{
|
||||
duplicator_node* n2
|
||||
= new duplicator_node(*i,
|
||||
*s,
|
||||
si->current_condition(),
|
||||
si->current_acceptance_conditions(),
|
||||
nb_node_parity_game++);
|
||||
duplicator_vertice_.push_back(n2);
|
||||
}
|
||||
}
|
||||
else
|
||||
delete p;
|
||||
}
|
||||
delete s;
|
||||
}
|
||||
delete si;
|
||||
}
|
||||
Sgi::vector<couple_bdd*>::iterator i2;
|
||||
for (i2 = trans->begin(); i2 != trans->end(); ++i2)
|
||||
{
|
||||
delete *i2;
|
||||
}
|
||||
delete trans;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph_direct::build_link()
|
||||
{
|
||||
int nb_ds = 0;
|
||||
int nb_sd = 0;
|
||||
spot::state* s = NULL;
|
||||
|
||||
// for each couple of (spoiler, duplicator)
|
||||
for (Sgi::vector<spoiler_node*>::iterator i
|
||||
= spoiler_vertice_.begin(); i != spoiler_vertice_.end(); ++i)
|
||||
{
|
||||
for (Sgi::vector<duplicator_node*>::iterator j
|
||||
= duplicator_vertice_.begin();
|
||||
j != duplicator_vertice_.end(); ++j)
|
||||
{
|
||||
// We add a link between a duplicator and a spoiler.
|
||||
if ((*j)->get_spoiler_node()->compare((*i)->get_spoiler_node()) == 0)
|
||||
{
|
||||
tgba_succ_iterator* si
|
||||
= automata_->succ_iter((*j)->get_duplicator_node());
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
s = si->current_state();
|
||||
if ((s->compare((*i)->get_duplicator_node()) == 0) &&
|
||||
(*j)->implies(si->current_condition(),
|
||||
si->current_acceptance_conditions()))
|
||||
{
|
||||
(*j)->add_succ(*i);
|
||||
nb_ds++;
|
||||
}
|
||||
delete s;
|
||||
}
|
||||
delete si;
|
||||
}
|
||||
|
||||
// We add a link between a spoiler and a duplicator.
|
||||
if ((*j)->get_duplicator_node()->compare((*i)->get_duplicator_node()) == 0)
|
||||
{
|
||||
tgba_succ_iterator* si
|
||||
= automata_->succ_iter((*i)->get_spoiler_node());
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
s = si->current_state();
|
||||
if ((s->compare((*j)->get_spoiler_node()) == 0) &&
|
||||
(*j)->match(si->current_condition(),
|
||||
si->current_acceptance_conditions()))
|
||||
{
|
||||
(*i)->add_succ(*j);
|
||||
nb_sd++;
|
||||
}
|
||||
delete s;
|
||||
}
|
||||
delete si;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph_direct::prune()
|
||||
{
|
||||
bool change = true;
|
||||
|
||||
while (change)
|
||||
{
|
||||
change = false;
|
||||
for (Sgi::vector<duplicator_node*>::iterator i
|
||||
= duplicator_vertice_.begin();
|
||||
i != duplicator_vertice_.end(); ++i)
|
||||
{
|
||||
change |= (*i)->set_win();
|
||||
}
|
||||
for (Sgi::vector<spoiler_node*>::iterator i
|
||||
= spoiler_vertice_.begin();
|
||||
i != spoiler_vertice_.end(); ++i)
|
||||
{
|
||||
change |= (*i)->set_win();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
simulation_relation*
|
||||
parity_game_graph_direct::get_relation()
|
||||
{
|
||||
simulation_relation* rel = new simulation_relation();
|
||||
state_couple* p = NULL;
|
||||
seen_map::iterator j;
|
||||
|
||||
for (Sgi::vector<spoiler_node*>::iterator i
|
||||
= spoiler_vertice_.begin();
|
||||
i != spoiler_vertice_.end(); ++i)
|
||||
{
|
||||
if (!(*i)->not_win)
|
||||
{
|
||||
p = new state_couple((*i)->get_spoiler_node(),
|
||||
(*i)->get_duplicator_node());
|
||||
rel->push_back(p);
|
||||
|
||||
|
||||
// We remove the state in rel from seen
|
||||
// because the destructor of
|
||||
// tgba_reachable_iterator_breadth_first
|
||||
// delete all the state.
|
||||
|
||||
|
||||
if ((j = seen.find(p->first)) != seen.end())
|
||||
seen.erase(j);
|
||||
if ((j = seen.find(p->second)) != seen.end())
|
||||
seen.erase(j);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
parity_game_graph_direct::~parity_game_graph_direct()
|
||||
{
|
||||
}
|
||||
|
||||
parity_game_graph_direct::parity_game_graph_direct(const tgba* a)
|
||||
: parity_game_graph(a)
|
||||
{
|
||||
this->build_couple();
|
||||
this->build_link();
|
||||
this->prune();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
simulation_relation*
|
||||
get_direct_relation_simulation(const tgba* f, int opt)
|
||||
{
|
||||
parity_game_graph_direct* G = new parity_game_graph_direct(f);
|
||||
simulation_relation* rel = G->get_relation();
|
||||
if (opt == 1)
|
||||
G->print(std::cout);
|
||||
delete G;
|
||||
return rel;
|
||||
}
|
||||
|
||||
void
|
||||
free_relation_simulation(simulation_relation* rel)
|
||||
{
|
||||
if (rel == NULL)
|
||||
return;
|
||||
|
||||
Sgi::hash_map<const spot::state*, int,
|
||||
state_ptr_hash, state_ptr_equal> seen;
|
||||
Sgi::hash_map<const spot::state*, int,
|
||||
state_ptr_hash, state_ptr_equal>::iterator j;
|
||||
|
||||
simulation_relation::iterator i;
|
||||
for (i = rel->begin(); i != rel->end(); ++i)
|
||||
{
|
||||
if ((j = seen.find((*i)->first)) == seen.end())
|
||||
seen[(*i)->first] = 0;
|
||||
|
||||
if ((j = seen.find((*i)->second)) == seen.end())
|
||||
seen[(*i)->second] = 0;
|
||||
|
||||
delete *i;
|
||||
}
|
||||
delete rel;
|
||||
rel = NULL;
|
||||
|
||||
for (j = seen.begin(); j != seen.end();)
|
||||
{
|
||||
const state* ptr = j->first;
|
||||
++j;
|
||||
delete(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
is_include(const tgba*, const tgba*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
tgba*
|
||||
reduc_tgba_sim(const tgba* f, int opt)
|
||||
{
|
||||
spot::tgba_reduc* automatareduc = new spot::tgba_reduc(f);
|
||||
|
||||
if (opt & Reduce_Dir_Sim)
|
||||
{
|
||||
simulation_relation* rel
|
||||
= get_direct_relation_simulation(automatareduc);
|
||||
|
||||
automatareduc->display_rel_sim(rel, std::cout);
|
||||
automatareduc->prune_automata(rel);
|
||||
|
||||
free_relation_simulation(rel);
|
||||
}
|
||||
else
|
||||
if (opt & Reduce_Del_Sim)
|
||||
{
|
||||
simulation_relation* rel
|
||||
= get_delayed_relation_simulation(automatareduc);
|
||||
|
||||
automatareduc->display_rel_sim(rel, std::cout);
|
||||
automatareduc->prune_automata(rel);
|
||||
|
||||
free_relation_simulation(rel);
|
||||
}
|
||||
|
||||
if (opt & Reduce_Scc)
|
||||
{
|
||||
automatareduc->compute_scc();
|
||||
automatareduc->prune_scc();
|
||||
}
|
||||
|
||||
return automatareduc;
|
||||
}
|
||||
|
||||
}
|
||||
314
src/tgbaalgos/reductgba_sim.hh
Normal file
314
src/tgbaalgos/reductgba_sim.hh
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Spot; see the file COPYING. If not, write to the Free
|
||||
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
|
||||
|
||||
#ifndef SPOT_REDUC_TGBA_SIM_HH
|
||||
#define SPOT_REDUC_TGBA_SIM_HH
|
||||
|
||||
#include "tgba/tgbareduc.hh"
|
||||
#include "tgbaalgos/reachiter.hh"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
/// Options for reduce.
|
||||
enum reduce_tgba_options
|
||||
{
|
||||
/// No reduction.
|
||||
Reduce_None = 0,
|
||||
/// Reduction using direct simulation relation.
|
||||
Reduce_Dir_Sim = 1,
|
||||
/// Reduction using delayed simulation relation.
|
||||
Reduce_Del_Sim = 2,
|
||||
/// Reduction using SCC.
|
||||
Reduce_Scc = 4,
|
||||
/// All reductions.
|
||||
Reduce_All = -1U
|
||||
};
|
||||
|
||||
/// \brief Remove some node of the automata using a simulation
|
||||
/// relation.
|
||||
///
|
||||
/// \param a the automata to reduce.
|
||||
/// \param opt a conjonction of spot::reduce_tgba_options specifying
|
||||
// which optimizations to apply.
|
||||
/// \return the reduced automata.
|
||||
tgba* reduc_tgba_sim(const tgba* a, int opt = Reduce_All);
|
||||
|
||||
/// \brief Compute a direct simulation relation on state of tgba \a f.
|
||||
simulation_relation* get_direct_relation_simulation(const tgba* a,
|
||||
int opt = -1);
|
||||
|
||||
/// Compute a delayed simulation relation on state of tgba \a f.
|
||||
/// FIXME : this method is incorrect !!
|
||||
/// Don't use it !!
|
||||
simulation_relation* get_delayed_relation_simulation(const tgba* a,
|
||||
int opt = -1);
|
||||
|
||||
/// To free a simulation relation.
|
||||
void free_relation_simulation(simulation_relation* rel);
|
||||
|
||||
/// Test if the initial state of a2 fair simulate this of a1.
|
||||
/// Not implemented.
|
||||
bool is_include(const tgba* a1, const tgba* a2);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// simulation.
|
||||
|
||||
class spoiler_node;
|
||||
class duplicator_node;
|
||||
|
||||
typedef Sgi::vector<spoiler_node*> sn_v;
|
||||
typedef Sgi::vector<duplicator_node*> dn_v;
|
||||
typedef Sgi::vector<const state*> s_v;
|
||||
|
||||
/// \brief Parity game graph which compute a simulation relation.
|
||||
class parity_game_graph : public tgba_reachable_iterator_breadth_first
|
||||
{
|
||||
public:
|
||||
parity_game_graph(const tgba* a);
|
||||
virtual ~parity_game_graph();
|
||||
|
||||
virtual simulation_relation* get_relation() = 0;
|
||||
|
||||
void print(std::ostream& os);
|
||||
|
||||
protected:
|
||||
sn_v spoiler_vertice_;
|
||||
dn_v duplicator_vertice_;
|
||||
s_v tgba_state_;
|
||||
int nb_node_parity_game;
|
||||
|
||||
void start();
|
||||
void end();
|
||||
void process_state(const state* s, int n, tgba_succ_iterator* si);
|
||||
void process_link(int in, int out, const tgba_succ_iterator* si);
|
||||
|
||||
/// \brief Compute each node of the graph.
|
||||
virtual void build_couple() = 0;
|
||||
|
||||
/// \brief Compute the link of the graph.
|
||||
/// Successor of spoiler node (resp. duplicator node)
|
||||
/// are duplicator node (resp. spoiler node).
|
||||
virtual void build_link() = 0;
|
||||
|
||||
/// \brief Remove edge from spoiler to duplicator that make
|
||||
/// duplicator loose.
|
||||
/// Spoiler node whose still have some link, reveal
|
||||
/// a direct simulation relation.
|
||||
virtual void prune() = 0;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Direct simulation.
|
||||
|
||||
/// Spoiler node of parity game graph.
|
||||
class spoiler_node
|
||||
{
|
||||
public:
|
||||
spoiler_node(const state* d_node,
|
||||
const state* s_node,
|
||||
int num);
|
||||
virtual ~spoiler_node();
|
||||
|
||||
void add_succ(spoiler_node* n);
|
||||
void del_succ(spoiler_node* n);
|
||||
virtual void add_pred(spoiler_node* n);
|
||||
virtual void del_pred();
|
||||
int get_nb_succ();
|
||||
bool prune();
|
||||
virtual bool set_win();
|
||||
virtual std::string to_string(const tgba* a);
|
||||
virtual std::string succ_to_string();
|
||||
|
||||
const state* get_spoiler_node();
|
||||
const state* get_duplicator_node();
|
||||
state_couple* get_pair();
|
||||
|
||||
bool not_win;
|
||||
int num_; // for the dot display.
|
||||
|
||||
protected:
|
||||
sn_v* lnode_succ;
|
||||
sn_v* lnode_pred;
|
||||
//Sgi::vector<spoiler_node*>* lnode_succ;
|
||||
state_couple* sc_;
|
||||
};
|
||||
|
||||
/// Duplicator node of parity game graph.
|
||||
class duplicator_node : public spoiler_node
|
||||
{
|
||||
public:
|
||||
duplicator_node(const state* d_node,
|
||||
const state* s_node,
|
||||
bdd l,
|
||||
bdd a,
|
||||
int num);
|
||||
virtual ~duplicator_node();
|
||||
|
||||
virtual bool set_win();
|
||||
virtual std::string to_string(const tgba* a);
|
||||
|
||||
bool match(bdd l, bdd a);
|
||||
bool implies(bdd l, bdd a);
|
||||
|
||||
protected:
|
||||
bdd label_;
|
||||
bdd acc_;
|
||||
};
|
||||
|
||||
/// Parity game graph which compute the direct simulation relation.
|
||||
class parity_game_graph_direct : public parity_game_graph
|
||||
{
|
||||
public:
|
||||
parity_game_graph_direct(const tgba* a);
|
||||
~parity_game_graph_direct();
|
||||
|
||||
virtual simulation_relation* get_relation();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void build_couple();
|
||||
virtual void build_link();
|
||||
virtual void prune();
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Delayed simulation.
|
||||
|
||||
/// Spoiler node of parity game graph for delayed simulation.
|
||||
class spoiler_node_delayed : public spoiler_node
|
||||
{
|
||||
public:
|
||||
spoiler_node_delayed(const state* d_node,
|
||||
const state* s_node,
|
||||
bdd a,
|
||||
int num);
|
||||
~spoiler_node_delayed();
|
||||
|
||||
/// Return true if the progress_measure has changed.
|
||||
bool set_win();
|
||||
bdd get_acceptance_condition_visited();
|
||||
|
||||
virtual std::string to_string(const tgba* a);
|
||||
|
||||
int get_progress_measure();
|
||||
|
||||
protected:
|
||||
/// a Bdd for retain all the acceptance condition
|
||||
/// that a node has visited.
|
||||
bdd acceptance_condition_visited_;
|
||||
int progress_measure_;
|
||||
|
||||
};
|
||||
|
||||
/// Duplicator node of parity game graph for delayed simulation.
|
||||
class duplicator_node_delayed : public duplicator_node
|
||||
{
|
||||
public:
|
||||
duplicator_node_delayed(const state* d_node,
|
||||
const state* s_node,
|
||||
bdd l,
|
||||
bdd a,
|
||||
int num);
|
||||
~duplicator_node_delayed();
|
||||
|
||||
/// Return true if the progress_measure has changed.
|
||||
bool set_win();
|
||||
virtual std::string to_string(const tgba* a);
|
||||
|
||||
bool implies_label(bdd l);
|
||||
bool implies_acc(bdd a);
|
||||
|
||||
int get_progress_measure();
|
||||
|
||||
protected:
|
||||
int progress_measure_;
|
||||
};
|
||||
|
||||
/// Parity game graph which compute the delayed simulation relation
|
||||
/// as explain in
|
||||
/// @inproceedings{ icalp2001,
|
||||
/// AUTHOR = {Etessami, Thomas Wilke, Rebecca A. Schuller},
|
||||
/// TITLE = {Fair Simulation Relations, Parity Games, and State Space
|
||||
/// Reduction for Buchi Automata},
|
||||
/// BOOKTITLE = {Automata, Languages and Programming,
|
||||
/// 28th international collquium},
|
||||
/// PAGES = {694--707},
|
||||
/// YEAR = 2001,
|
||||
/// EDITOR = {Orejas, Fernando and Spirakis, Paul G. and van Leeuwen, Jan},
|
||||
/// VOLUME = 2076,
|
||||
/// SERIES = {Lecture Notes in Computer Science},
|
||||
/// ADDRESS = {Crete, Greece},
|
||||
/// MONTH = JUL,
|
||||
/// PUBLISHER = {Springer},
|
||||
/// url = {citeseer.ist.psu.edu/472661.html}
|
||||
/// }
|
||||
|
||||
class parity_game_graph_delayed : public parity_game_graph
|
||||
{
|
||||
public:
|
||||
parity_game_graph_delayed(const tgba* a);
|
||||
~parity_game_graph_delayed();
|
||||
|
||||
virtual simulation_relation* get_relation();
|
||||
|
||||
private:
|
||||
|
||||
/// Vector which contain all the sub-set of the set
|
||||
/// of acceptance condition.
|
||||
typedef Sgi::vector<bdd> bdd_v;
|
||||
bdd_v sub_set_acc_cond_;
|
||||
|
||||
/// Return the number of acceptance condition.
|
||||
int nb_set_acc_cond();
|
||||
|
||||
/// Compute sub_set_acc_cond_;
|
||||
void build_sub_set_acc_cond();
|
||||
|
||||
/// Add a duplicator node, and
|
||||
/// all his successor (spoiler node) which
|
||||
/// have a acceptance_condition_visited_ != bddfalse
|
||||
void add_dup_node(state* ss,
|
||||
state* sd,
|
||||
bdd l,
|
||||
bdd a);
|
||||
|
||||
/// \brief Compute the couple as for direct simulation,
|
||||
virtual void build_couple();
|
||||
virtual void build_link();
|
||||
void build_recurse_successor_spoiler(spoiler_node* sn);
|
||||
void build_recurse_successor_duplicator(duplicator_node* dn);
|
||||
|
||||
/// \brief The Jurdzinski's lifting algorithm.
|
||||
void lift();
|
||||
|
||||
/// \brief Remove all node so as to there is no dead ends (terminal node).
|
||||
virtual void prune();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
816
src/tgbaalgos/reductgba_sim_del.cc
Normal file
816
src/tgbaalgos/reductgba_sim_del.cc
Normal file
|
|
@ -0,0 +1,816 @@
|
|||
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Spot; see the file COPYING. If not, write to the Free
|
||||
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
|
||||
#include "reductgba_sim.hh"
|
||||
#include "tgba/bddprint.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
/// Number of spoiler node with a one priority (see icalp2001).
|
||||
/// The one priority is represent by a \a acceptance_condition_visited_
|
||||
/// which differ of bddfalse.
|
||||
/// This spoiler node are looser for the duplicator.
|
||||
static int nb_spoiler_loose_;
|
||||
|
||||
static int nb_spoiler;
|
||||
static int nb_duplicator;
|
||||
|
||||
//static int nb_node;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// spoiler_node_delayed
|
||||
|
||||
spoiler_node_delayed::spoiler_node_delayed(const state* d_node,
|
||||
const state* s_node,
|
||||
bdd a,
|
||||
int num)
|
||||
: spoiler_node(d_node, s_node, num),
|
||||
acceptance_condition_visited_(a)
|
||||
{
|
||||
nb_spoiler++;
|
||||
progress_measure_ = 0;
|
||||
if (acceptance_condition_visited_ == bddfalse)
|
||||
nb_spoiler_loose_++;
|
||||
}
|
||||
|
||||
spoiler_node_delayed::~spoiler_node_delayed()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
spoiler_node_delayed::set_win()
|
||||
{
|
||||
// We take the max of the progress measure of the successor node
|
||||
// because we are on a spoiler.
|
||||
|
||||
//std::cout << "spoiler_node_delayed::set_win" << std::endl;
|
||||
|
||||
if (lnode_succ->size() == 0)
|
||||
progress_measure_ = nb_spoiler_loose_;
|
||||
|
||||
if (progress_measure_ >= nb_spoiler_loose_)
|
||||
return false;
|
||||
|
||||
bool change;
|
||||
int tmpmax = 0;
|
||||
int tmp = 0;
|
||||
sn_v::iterator i = lnode_succ->begin();
|
||||
if (i != lnode_succ->end())
|
||||
{
|
||||
tmpmax =
|
||||
dynamic_cast<duplicator_node_delayed*>(*i)->get_progress_measure();
|
||||
++i;
|
||||
}
|
||||
for (; i != lnode_succ->end(); ++i)
|
||||
{
|
||||
tmp =
|
||||
dynamic_cast<duplicator_node_delayed*>(*i)->get_progress_measure();
|
||||
if (tmp > tmpmax)
|
||||
tmpmax = tmp;
|
||||
}
|
||||
|
||||
// If the priority of the node is 1
|
||||
// acceptance_condition_visited_ != bddfalse
|
||||
// then we increment the progress measure of 1.
|
||||
if (acceptance_condition_visited_ != bddfalse)
|
||||
tmpmax++;
|
||||
|
||||
change = (progress_measure_ < tmpmax);
|
||||
|
||||
progress_measure_ = tmpmax;
|
||||
return change;
|
||||
}
|
||||
|
||||
std::string
|
||||
spoiler_node_delayed::to_string(const tgba* a)
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
||||
// print the node.
|
||||
os << num_
|
||||
<< " [shape=box, label=\"("
|
||||
<< a->format_state(sc_->first)
|
||||
<< ", "
|
||||
<< a->format_state(sc_->second)
|
||||
<< ", ";
|
||||
//bdd_print_acc(os, a->get_dict(), acceptance_condition_visited_);
|
||||
if (acceptance_condition_visited_ == bddfalse)
|
||||
{
|
||||
os << "false";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "ACC";
|
||||
}
|
||||
os << ")"
|
||||
<< " pm = " << progress_measure_ << "\"]"
|
||||
<< std::endl;
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
bdd
|
||||
spoiler_node_delayed::get_acceptance_condition_visited()
|
||||
{
|
||||
return acceptance_condition_visited_;
|
||||
}
|
||||
|
||||
int
|
||||
spoiler_node_delayed::get_progress_measure()
|
||||
{
|
||||
if ((acceptance_condition_visited_ == bddfalse) &&
|
||||
(progress_measure_ != (nb_spoiler_loose_ + 1)))
|
||||
return 0;
|
||||
else
|
||||
return progress_measure_;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// duplicator_node_delayed
|
||||
|
||||
duplicator_node_delayed::duplicator_node_delayed(const state* d_node,
|
||||
const state* s_node,
|
||||
bdd l,
|
||||
bdd a,
|
||||
int num)
|
||||
: duplicator_node(d_node, s_node, l, a, num)
|
||||
{
|
||||
nb_duplicator++;
|
||||
progress_measure_ = 0;
|
||||
}
|
||||
|
||||
duplicator_node_delayed::~duplicator_node_delayed()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
duplicator_node_delayed::set_win()
|
||||
{
|
||||
// We take the min of the progress measure of the successor node
|
||||
// because we are on a duplicator.
|
||||
|
||||
//std::cout << "duplicator_node_delayed::set_win" << std::endl;
|
||||
|
||||
//bool debug = true;
|
||||
|
||||
if (progress_measure_ == nb_spoiler_loose_)
|
||||
return false;
|
||||
|
||||
bool change;
|
||||
int tmpmin = 0;
|
||||
int tmp = 0;
|
||||
sn_v::iterator i = lnode_succ->begin();
|
||||
if (i != lnode_succ->end())
|
||||
{
|
||||
tmpmin = dynamic_cast<spoiler_node_delayed*>(*i)->get_progress_measure();
|
||||
/*
|
||||
debug &= (dynamic_cast<spoiler_node_delayed*>(*i)
|
||||
->get_acceptance_condition_visited()
|
||||
!= bddfalse);
|
||||
*/
|
||||
++i;
|
||||
}
|
||||
for (; i != lnode_succ->end(); ++i)
|
||||
{
|
||||
/*
|
||||
debug &= (dynamic_cast<spoiler_node_delayed*>(*i)
|
||||
->get_acceptance_condition_visited()
|
||||
!= bddfalse);
|
||||
*/
|
||||
tmp = dynamic_cast<spoiler_node_delayed*>(*i)->get_progress_measure();
|
||||
if (tmp < tmpmin)
|
||||
tmpmin = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
if (debug)
|
||||
std::cout << "All successor p = 1" << std::endl;
|
||||
else
|
||||
std::cout << "Not All successor p = 1" << std::endl;
|
||||
*/
|
||||
|
||||
change = (progress_measure_ < tmpmin);
|
||||
progress_measure_ = tmpmin;
|
||||
return change;
|
||||
}
|
||||
|
||||
std::string
|
||||
duplicator_node_delayed::to_string(const tgba* a)
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
||||
// print the node.
|
||||
os << num_
|
||||
<< " [shape=box, label=\"("
|
||||
<< a->format_state(sc_->first)
|
||||
<< ", "
|
||||
<< a->format_state(sc_->second);
|
||||
//<< ", ";
|
||||
//bdd_print_acc(os, a->get_dict(), acc_);
|
||||
os << ")"
|
||||
<< " pm = " << progress_measure_ << "\"]"
|
||||
<< std::endl;
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
bool
|
||||
duplicator_node_delayed::implies_label(bdd l)
|
||||
{
|
||||
return ((l | !label_) == bddtrue);
|
||||
}
|
||||
|
||||
bool
|
||||
duplicator_node_delayed::implies_acc(bdd a)
|
||||
{
|
||||
return ((a | !acc_) == bddtrue);
|
||||
}
|
||||
|
||||
int
|
||||
duplicator_node_delayed::get_progress_measure()
|
||||
{
|
||||
return progress_measure_;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// parity_game_graph_delayed
|
||||
|
||||
int
|
||||
parity_game_graph_delayed::nb_set_acc_cond()
|
||||
{
|
||||
bdd acc, all;
|
||||
acc = all = automata_->all_acceptance_conditions();
|
||||
int count = 0;
|
||||
while (all != bddfalse)
|
||||
{
|
||||
sub_set_acc_cond_.push_back(bdd_satone(all));
|
||||
all -= bdd_satone(all);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph_delayed::build_sub_set_acc_cond()
|
||||
{
|
||||
// compute the number of acceptance conditions
|
||||
bdd acc, all;
|
||||
acc = all = automata_->all_acceptance_conditions();
|
||||
int count = 0;
|
||||
while (all != bddfalse)
|
||||
{
|
||||
//std::cout << "add acc" << std::endl;
|
||||
sub_set_acc_cond_.push_back(bdd_satone(all));
|
||||
all -= bdd_satone(all);
|
||||
count++;
|
||||
}
|
||||
// sub_set_acc_cond_ contains all the acceptance condition.
|
||||
// but we must have all the sub-set of acceptance condition.
|
||||
// In fact we must have 2^count sub-set.
|
||||
|
||||
if (count == 2)
|
||||
{
|
||||
sub_set_acc_cond_.push_back(acc);
|
||||
sub_set_acc_cond_.push_back(bddfalse);
|
||||
}
|
||||
|
||||
/*
|
||||
bdd_v::iterator i;
|
||||
|
||||
bdd_v::iterator j;
|
||||
for (i = sub_set_acc_cond_.begin(); i != sub_set_acc_cond_.end(); ++i)
|
||||
for (j = sub_set_acc_cond_.begin(); j != sub_set_acc_cond_.end(); ++j)
|
||||
sub_set_acc_cond_.push_back(*i | *j);
|
||||
|
||||
std::cout << std::endl;
|
||||
for (i = sub_set_acc_cond_.begin(); i != sub_set_acc_cond_.end();)
|
||||
{
|
||||
bdd_print_acc(std::cout, automata_->get_dict(), *i);
|
||||
std::cout << " // " << std::endl;
|
||||
++i;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
parity_game_graph_delayed::build_couple()
|
||||
{
|
||||
//std::cout << "build couple" << std::endl;
|
||||
|
||||
nb_spoiler = 0;
|
||||
nb_duplicator = 0;
|
||||
|
||||
tgba_succ_iterator* si = NULL;
|
||||
typedef Sgi::pair<bdd, bdd> couple_bdd;
|
||||
couple_bdd *p = NULL;
|
||||
Sgi::vector<couple_bdd*>* trans = NULL;
|
||||
bool exist = false;
|
||||
spot::state* s = NULL;
|
||||
|
||||
s_v::iterator i;
|
||||
for (i = tgba_state_.begin(); i != tgba_state_.end(); ++i)
|
||||
{
|
||||
|
||||
// for each sub-set of the set of acceptance condition.
|
||||
bdd_v::iterator i2;
|
||||
for (i2 = sub_set_acc_cond_.begin();
|
||||
i2 != sub_set_acc_cond_.end(); ++i2)
|
||||
{
|
||||
|
||||
// spoiler node are all state couple (i,j)
|
||||
// multiply by 2^(|F|)
|
||||
s_v::iterator i3;
|
||||
for (i3 = tgba_state_.begin();
|
||||
i3 != tgba_state_.end(); ++i3)
|
||||
{
|
||||
//nb_spoiler++;
|
||||
spoiler_node_delayed* n1
|
||||
= new spoiler_node_delayed(*i,
|
||||
*i3,
|
||||
*i2,
|
||||
nb_node_parity_game++);
|
||||
spoiler_vertice_.push_back(n1);
|
||||
}
|
||||
|
||||
// duplicator node are all state couple where
|
||||
// the first state i are reachable.
|
||||
trans = new Sgi::vector<couple_bdd*>;
|
||||
for (i3 = tgba_state_.begin();
|
||||
i3 != tgba_state_.end(); ++i3)
|
||||
{
|
||||
si = automata_->succ_iter(*i3);
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
|
||||
// if there exist a predecessor of i named j
|
||||
s = si->current_state();
|
||||
if (s->compare(*i) == 0)
|
||||
{
|
||||
|
||||
// p is the label of the transition j->i
|
||||
p = new couple_bdd(si->current_condition(),
|
||||
si->current_acceptance_conditions());
|
||||
|
||||
// If an other predecessor of i has the same label p
|
||||
// to reach i, then we don't compute the
|
||||
// duplicator node.
|
||||
exist = false;
|
||||
Sgi::vector<couple_bdd*>::iterator i4;
|
||||
for (i4 = trans->begin();
|
||||
i4 != trans->end(); ++i4)
|
||||
{
|
||||
if ((si->current_condition() == (*i4)->first))
|
||||
// We don't need the acceptance condition
|
||||
//&&
|
||||
//(si->current_acceptance_conditions()
|
||||
//== (*i4)->second))
|
||||
exist = true;
|
||||
}
|
||||
|
||||
if (!exist)
|
||||
{
|
||||
// We build all the state couple with the label p.
|
||||
// multiply by 2^(|F|)
|
||||
trans->push_back(p);
|
||||
Sgi::vector<const state*>::iterator i5;
|
||||
for (i5 = tgba_state_.begin();
|
||||
i5 != tgba_state_.end(); ++i5)
|
||||
{
|
||||
//nb_duplicator++;
|
||||
int nb = nb_node_parity_game++;
|
||||
duplicator_node_delayed* n2
|
||||
= new
|
||||
duplicator_node_delayed(*i,
|
||||
*i5,
|
||||
si->
|
||||
current_condition(),
|
||||
*i2,
|
||||
nb);
|
||||
duplicator_vertice_.push_back(n2);
|
||||
}
|
||||
}
|
||||
else
|
||||
delete p;
|
||||
}
|
||||
delete s;
|
||||
}
|
||||
delete si;
|
||||
}
|
||||
Sgi::vector<couple_bdd*>::iterator i6;
|
||||
for (i6 = trans->begin(); i6 != trans->end(); ++i6)
|
||||
{
|
||||
delete *i6;
|
||||
}
|
||||
delete trans;
|
||||
}
|
||||
}
|
||||
nb_spoiler_loose_++;
|
||||
|
||||
//std::cout << "spoiler node : " << nb_spoiler << std::endl;
|
||||
//std::cout << "duplicator node : " << nb_duplicator << std::endl;
|
||||
//std::cout << "nb_spoiler_loose_ : " << nb_spoiler_loose_ << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph_delayed::build_link()
|
||||
{
|
||||
//std::cout << "build link" << std::endl;
|
||||
int nb_ds = 0;
|
||||
int nb_sd = 0;
|
||||
spot::state* s = NULL;
|
||||
|
||||
// for each couple of (spoiler, duplicator)
|
||||
sn_v::iterator i;
|
||||
for (i = spoiler_vertice_.begin(); i != spoiler_vertice_.end(); ++i)
|
||||
{
|
||||
dn_v::iterator i2;
|
||||
for (i2 = duplicator_vertice_.begin();
|
||||
i2 != duplicator_vertice_.end(); ++i2)
|
||||
{
|
||||
|
||||
// We add a link between a duplicator and a spoiler.
|
||||
if ((*i2)->get_spoiler_node()->compare((*i)
|
||||
->get_spoiler_node()) == 0)
|
||||
{
|
||||
tgba_succ_iterator* si
|
||||
= automata_->succ_iter((*i2)->get_duplicator_node());
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
s = si->current_state();
|
||||
|
||||
bdd btmp2 = dynamic_cast<spoiler_node_delayed*>(*i)->
|
||||
get_acceptance_condition_visited();
|
||||
bdd btmp = btmp2 - si->current_acceptance_conditions();
|
||||
|
||||
//if ((s->compare((*i)->get_duplicator_node()) == 0) &&
|
||||
//dynamic_cast<duplicator_node_delayed*>(*i2)->
|
||||
// implies_label(si->current_condition()) &&
|
||||
//(btmp == btmp2))
|
||||
|
||||
if ((s->compare((*i)->get_duplicator_node()) == 0) &&
|
||||
dynamic_cast<duplicator_node_delayed*>(*i2)->
|
||||
implies_label(si->current_condition()) &&
|
||||
(dynamic_cast<spoiler_node_delayed*>(*i)->
|
||||
get_acceptance_condition_visited() != bddfalse))
|
||||
{
|
||||
//std::cout << "add duplicator -> spoiler" << std::endl;
|
||||
(*i2)->add_succ(*i);
|
||||
(*i)->add_pred(*i2);
|
||||
nb_ds++;
|
||||
}
|
||||
delete s;
|
||||
}
|
||||
delete si;
|
||||
}
|
||||
|
||||
// We add a link between a spoiler and a duplicator.
|
||||
if ((*i2)->get_duplicator_node()
|
||||
->compare((*i)->get_duplicator_node()) == 0)
|
||||
{
|
||||
tgba_succ_iterator* si
|
||||
= automata_->succ_iter((*i)->get_spoiler_node());
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
s = si->current_state();
|
||||
|
||||
bdd btmp = si->current_acceptance_conditions() |
|
||||
dynamic_cast<spoiler_node_delayed*>(*i)->
|
||||
get_acceptance_condition_visited();
|
||||
if ((s->compare((*i2)->get_spoiler_node()) == 0) &&
|
||||
(*i2)->match(si->current_condition(), btmp))
|
||||
{
|
||||
//std::cout << "add spoiler -> duplicator" << std::endl;
|
||||
(*i)->add_succ(*i2);
|
||||
(*i2)->add_pred(*i);
|
||||
nb_sd++;
|
||||
}
|
||||
delete s;
|
||||
}
|
||||
delete si;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// We build only node which are reachable
|
||||
void
|
||||
parity_game_graph_delayed::build_couple()
|
||||
{
|
||||
// We build only some "basic" spoiler node.
|
||||
|
||||
s_v::iterator i;
|
||||
for (i = tgba_state_.begin(); i != tgba_state_.end(); ++i)
|
||||
{
|
||||
|
||||
// spoiler node are all state couple (i,j)
|
||||
s_v::iterator i2;
|
||||
for (i2 = tgba_state_.begin();
|
||||
i2 != tgba_state_.end(); ++i2)
|
||||
{
|
||||
std::cout << "add spoiler node" << std::endl;
|
||||
nb_spoiler++;
|
||||
spoiler_node_delayed* n1
|
||||
= new spoiler_node_delayed(*i, *i2,
|
||||
bddfalse,
|
||||
nb_node_parity_game++);
|
||||
spoiler_vertice_.push_back(n1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph_delayed::build_link()
|
||||
{
|
||||
// We create when it's possible a duplicator node
|
||||
// and recursively his successor.
|
||||
|
||||
spot::state* s1 = NULL;
|
||||
bool exist_pred = false;
|
||||
|
||||
sn_v::iterator i1;
|
||||
for (i1 = spoiler_vertice_.begin(); i1 != spoiler_vertice_.end(); ++i1)
|
||||
{
|
||||
exist_pred = false;
|
||||
// We check if there is a predecessor only if the duplicator
|
||||
// is the initial state.
|
||||
s1 = automata_->get_init_state();
|
||||
if (s1->compare((*i1)->get_duplicator_node()) == 0)
|
||||
{
|
||||
tgba_succ_iterator* si;
|
||||
s_v::iterator i2;
|
||||
spot::state* s2 = NULL;
|
||||
for (i2 = tgba_state_.begin();
|
||||
i2 != tgba_state_.end(); ++i2)
|
||||
{
|
||||
si = automata_->succ_iter(*i2);
|
||||
s2 = si->current_state();
|
||||
if (s2->compare(s1) == 0)
|
||||
exist_pred = true;
|
||||
delete s2;
|
||||
}
|
||||
}
|
||||
else
|
||||
exist_pred = true;
|
||||
delete s1;
|
||||
|
||||
if (!exist_pred)
|
||||
continue;
|
||||
|
||||
// We add a link between a spoiler and a (new) duplicator.
|
||||
// The acc of the duplicator must contains the
|
||||
// acceptance_condition_visited_ of the spoiler.
|
||||
build_recurse_successor_spoiler(*i1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph_delayed::build_recurse_successor_spoiler(spoiler_node* sn)
|
||||
{
|
||||
tgba_succ_iterator* si = automata_->succ_iter(sn->get_spoiler_node());
|
||||
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
bdd btmp = si->current_acceptance_conditions() |
|
||||
dynamic_cast<spoiler_node_delayed*>(sn)->
|
||||
get_acceptance_condition_visited();
|
||||
|
||||
s_v::iterator i1;
|
||||
state* s;
|
||||
for (i1 = tgba_state_.begin();
|
||||
i1 != tgba_state_.end(); ++i1)
|
||||
{
|
||||
s = si->current_state();
|
||||
if (s->compare(*i1) == 0)
|
||||
{
|
||||
duplicator_node_delayed* dn
|
||||
= new duplicator_node_delayed(*i1,
|
||||
sn->get_duplicator_node(),
|
||||
si->current_condition(),
|
||||
btmp,
|
||||
nb_node_parity_game++);
|
||||
duplicator_vertice_.push_back(dn);
|
||||
|
||||
sn->add_succ(dn);
|
||||
(dn)->add_pred(sn);
|
||||
|
||||
build_recurse_successor_duplicator(dn);
|
||||
}
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
delete si;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph_delayed::
|
||||
build_recurse_successor_duplicator(duplicator_node* dn)
|
||||
{
|
||||
tgba_succ_iterator* si = automata_->succ_iter(sn->get_spoiler_node());
|
||||
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
bdd btmp =
|
||||
dynamic_cast<spoiler_node_delayed*>(sn)->
|
||||
get_acceptance_condition_visited();
|
||||
bdd btmp2 = btmp - si->current_acceptance_conditions();
|
||||
|
||||
s_v::iterator i1;
|
||||
state* s;
|
||||
for (i1 = tgba_state_.begin();
|
||||
i1 != tgba_state_.end(); ++i1)
|
||||
{
|
||||
s = si->current_state();
|
||||
if (s->compare(*i1) == 0)
|
||||
{
|
||||
spoiler_node_delayed* sn
|
||||
= new spoiler_node_delayed(sn->get_spoiler_node(),
|
||||
*i1,
|
||||
bddtmp2,
|
||||
nb_node_parity_game++);
|
||||
spoiler_vertice_.push_back(n1);
|
||||
|
||||
sn->add_succ(dn);
|
||||
(dn)->add_pred(sn);
|
||||
|
||||
build_recurse_successor_spoiler(sn);
|
||||
|
||||
}
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
delete si;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
parity_game_graph_delayed::add_dup_node(state*,
|
||||
state*,
|
||||
bdd,
|
||||
bdd)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph_delayed::prune()
|
||||
{
|
||||
|
||||
bool change = true;
|
||||
|
||||
while (change)
|
||||
{
|
||||
change = false;
|
||||
for (Sgi::vector<duplicator_node*>::iterator i
|
||||
= duplicator_vertice_.begin();
|
||||
i != duplicator_vertice_.end();)
|
||||
{
|
||||
if ((*i)->get_nb_succ() == 0)
|
||||
{
|
||||
(*i)->del_pred();
|
||||
delete *i;
|
||||
i = duplicator_vertice_.erase(i);
|
||||
change = true;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
for (Sgi::vector<spoiler_node*>::iterator i
|
||||
= spoiler_vertice_.begin();
|
||||
i != spoiler_vertice_.end();)
|
||||
{
|
||||
if ((*i)->get_nb_succ() == 0)
|
||||
{
|
||||
(*i)->del_pred();
|
||||
delete *i;
|
||||
i = spoiler_vertice_.erase(i);
|
||||
change = true;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
parity_game_graph_delayed::lift()
|
||||
{
|
||||
// Jurdzinski's algorithm
|
||||
//int iter = 0;
|
||||
bool change = true;
|
||||
|
||||
while (change)
|
||||
{
|
||||
change = false;
|
||||
for (Sgi::vector<duplicator_node*>::iterator i
|
||||
= duplicator_vertice_.begin();
|
||||
i != duplicator_vertice_.end(); ++i)
|
||||
{
|
||||
change |= (*i)->set_win();
|
||||
}
|
||||
for (Sgi::vector<spoiler_node*>::iterator i
|
||||
= spoiler_vertice_.begin();
|
||||
i != spoiler_vertice_.end(); ++i)
|
||||
{
|
||||
change |= (*i)->set_win();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
simulation_relation*
|
||||
parity_game_graph_delayed::get_relation()
|
||||
{
|
||||
simulation_relation* rel = new simulation_relation();
|
||||
state_couple* p = NULL;
|
||||
seen_map::iterator j;
|
||||
|
||||
for (Sgi::vector<spoiler_node*>::iterator i
|
||||
= spoiler_vertice_.begin();
|
||||
i != spoiler_vertice_.end(); ++i)
|
||||
{
|
||||
if (dynamic_cast<spoiler_node_delayed*>(*i)->get_progress_measure()
|
||||
< nb_spoiler_loose_)
|
||||
{
|
||||
p = new state_couple((*i)->get_spoiler_node(),
|
||||
(*i)->get_duplicator_node());
|
||||
rel->push_back(p);
|
||||
|
||||
// We remove the state in rel from seen
|
||||
// because the destructor of
|
||||
// tgba_reachable_iterator_breadth_first
|
||||
// delete all the state.
|
||||
|
||||
if ((j = seen.find(p->first)) != seen.end())
|
||||
seen.erase(j);
|
||||
if ((j = seen.find(p->second)) != seen.end())
|
||||
seen.erase(j);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
parity_game_graph_delayed::~parity_game_graph_delayed()
|
||||
{
|
||||
}
|
||||
|
||||
parity_game_graph_delayed::parity_game_graph_delayed(const tgba* a)
|
||||
: parity_game_graph(a)
|
||||
{
|
||||
nb_spoiler_loose_ = 0;
|
||||
/*
|
||||
if (this->nb_set_acc_cond() > 2)
|
||||
return;
|
||||
this->build_sub_set_acc_cond();
|
||||
*/
|
||||
this->build_couple();
|
||||
this->build_link();
|
||||
this->prune();
|
||||
this->lift();
|
||||
//this->print(std::cout);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
simulation_relation*
|
||||
get_delayed_relation_simulation(const tgba* f, int opt)
|
||||
{
|
||||
/// FIXME : this method is incorrect !!
|
||||
/// Don't use it !!
|
||||
parity_game_graph_delayed* G = new parity_game_graph_delayed(f);
|
||||
simulation_relation* rel = G->get_relation();
|
||||
if (opt == 1)
|
||||
G->print(std::cout);
|
||||
delete G;
|
||||
return rel;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue