Commit 8be67c19 authored by martinez's avatar martinez
Browse files

* src/tgbatest/reduccmp.test: Bug.

* src/tgbatest/reductgba.test: More Test.

* src/tgbatest/ltl2tgba.cc: Adjust ...
* src/tgbaalgos/reductgba_sim_del.cc, src/tgbaalgos/reductgba_sim.hh,
src/tgbaalgos/reductgba_sim.cc: try to optimize.

* src/tgba/tgbareduc.hh, src/tgba/tgbareduc.cc: Scc reduction
and we remove some acceptance condition in scc which are not accepting.
* src/ltlvisit/syntimpl.cc : Some case wasn't detect.
* src/ltlvisit/basicreduce.cc: Case FGa || FGb = F(Ga | Gb) added.
* src/ltltest/syntimpl.test: More Test.
* src/ltltest/syntimpl.cc: Put the formula in negative normal form.
parent acee9e75
2004-06-28 Thomas Martinez <martinez@src.lip6.fr>
* src/tgbatest/reduccmp.test: Bug.
* src/tgbatest/reductgba.test: More Test.
* src/tgbatest/ltl2tgba.cc: Adjust ...
* src/tgbaalgos/reductgba_sim_del.cc, src/tgbaalgos/reductgba_sim.hh,
src/tgbaalgos/reductgba_sim.cc: try to optimize.
* src/tgba/tgbareduc.hh, src/tgba/tgbareduc.cc: Scc reduction
and we remove some acceptance condition in scc which are not accepting.
* src/ltlvisit/syntimpl.cc : Some case wasn't detect.
* src/ltlvisit/basicreduce.cc: Case FGa || FGb = F(Ga | Gb) added.
* src/ltltest/syntimpl.test: More Test.
* src/ltltest/syntimpl.cc: Put the formula in negative normal form.
2004-06-28 Alexandre Duret-Lutz <adl@src.lip6.fr>
* buddy/: Merge buddy-2-3.
......
......@@ -29,6 +29,7 @@
#include "ltlvisit/tostring.hh"
#include "ltlvisit/syntimpl.hh"
#include "ltlast/allnodes.hh"
#include "ltlvisit/nenoform.hh"
void
syntax(char* prog)
......@@ -46,17 +47,20 @@ main(int argc, char** argv)
int opt = atoi(argv[1]);
spot::ltl::parse_error_list p1;
spot::ltl::formula* f1 = spot::ltl::parse(argv[2], p1);
spot::ltl::formula* ftmp1 = spot::ltl::parse(argv[2], p1);
if (spot::ltl::format_parse_errors(std::cerr, argv[2], p1))
return 2;
spot::ltl::parse_error_list p2;
spot::ltl::formula* f2 = spot::ltl::parse(argv[3], p2);
spot::ltl::formula* ftmp2 = spot::ltl::parse(argv[3], p2);
if (spot::ltl::format_parse_errors(std::cerr, argv[3], p2))
return 2;
spot::ltl::formula* f1 = spot::ltl::negative_normal_form(ftmp1);
spot::ltl::formula* f2 = spot::ltl::negative_normal_form(ftmp2);
std::string f1s = spot::ltl::to_string(f1);
std::string f2s = spot::ltl::to_string(f2);
......@@ -99,6 +103,8 @@ main(int argc, char** argv)
spot::ltl::destroy(f1);
spot::ltl::destroy(f2);
spot::ltl::destroy(ftmp1);
spot::ltl::destroy(ftmp2);
assert(spot::ltl::atomic_prop::instance_count() == 0);
assert(spot::ltl::unop::instance_count() == 0);
assert(spot::ltl::binop::instance_count() == 0);
......
......@@ -26,6 +26,13 @@
. ./defs || exit 1
#
#GFa && GFb && FG(!a && !b)
run 1 ./syntimpl 0 'a' 'a | b'
run 1 ./syntimpl 0 'F(a)' 'F(a | b)'
run 1 ./syntimpl 0 'G(a)' 'G(a | b)'
run 1 ./syntimpl 0 'GF(a)' 'GF(a | b)'
run 1 ./syntimpl 0 'GF(a)' '!FG(!a && !b)'
run 1 ./syntimpl 0 'Xa' 'X(b U a)'
run 1 ./syntimpl 0 'XXa' 'XX(b U a)'
......
......@@ -425,6 +425,11 @@ namespace spot
unop* uo2 = dynamic_cast<unop*>(uo->child());
tmpGF->push_back(clone(uo2->child()));
}
else if (is_FG(*i))
{
// FG(a) | FG(b) = F(Ga | Gb)
tmpFG->push_back(clone(uo->child()));
}
else
{
tmpOther->push_back(clone(*i));
......@@ -501,8 +506,10 @@ namespace spot
destroy(*i);
}
delete tmpFG;
tmpFG = 0;
/*
delete tmpFG;
tmpFG = 0;
*/
break;
}
......@@ -546,11 +553,17 @@ namespace spot
if (tmpFG && tmpFG->size())
{
formula* ftmp
= unop::instance(unop::F,
unop::instance(unop::G,
multop::instance(mo->op(),
tmpFG)));
formula* ftmp = 0;
if (mo->op() == multop::And)
ftmp
= unop::instance(unop::F,
unop::instance(unop::G,
multop::instance(mo->op(),
tmpFG)));
else
ftmp
= unop::instance(unop::F,
multop::instance(mo->op(), tmpFG));
tmpOther->push_back(ftmp);
}
else if (tmpFG && !tmpFG->size())
......
......@@ -258,6 +258,8 @@ namespace spot
{
const formula* f1 = bo->first();
const formula* f2 = bo->second();
const binop* fb = dynamic_cast<const binop*>(f);
const unop* fu = dynamic_cast<const unop*>(f);
switch (bo->op())
{
case binop::Xor:
......@@ -269,6 +271,20 @@ namespace spot
result_ = true;
return;
case binop::R:
if (fb && fb->op() == binop::R)
if (syntactic_implication(fb->first(), f1) &&
syntactic_implication(fb->second(), f2))
{
result_ = true;
return;
}
if (fu && fu->op() == unop::G)
if (f1 == constant::false_instance() &&
syntactic_implication(fu->child(), f2))
{
result_ = true;
return;
}
if (syntactic_implication(f, f1)
&& syntactic_implication(f, f2))
result_ = true;
......@@ -411,7 +427,7 @@ namespace spot
}
case unop::G:
{
/* F(a) = false R a */
/* G(a) = false R a */
const formula* tmp = binop::instance(binop::R,
constant::false_instance(),
clone(f1));
......@@ -421,7 +437,7 @@ namespace spot
destroy(tmp);
return;
}
if (syntactic_implication(f1, f))
if (syntactic_implication(tmp, f))
result_ = true;
destroy(tmp);
return;
......@@ -442,6 +458,8 @@ namespace spot
const formula* f1 = bo->first();
const formula* f2 = bo->second();
const binop* fb = dynamic_cast<const binop*>(f);
const unop* fu = dynamic_cast<const unop*>(f);
switch (bo->op())
{
case binop::Xor:
......@@ -449,11 +467,33 @@ namespace spot
case binop::Implies:
return;
case binop::U:
/* (a < c) && (c < d) => a U b < c U d */
if (fb && fb->op() == binop::U)
if (syntactic_implication(f1, fb->first()) &&
syntactic_implication(f2, fb->second()))
{
result_ = true;
return;
}
if (fu && fu->op() == unop::F)
if (f1 == constant::true_instance() &&
syntactic_implication(f2, fu->child()))
{
result_ = true;
return;
}
if (syntactic_implication(f1, f)
&& syntactic_implication(f2, f))
result_ = true;
return;
case binop::R:
if (fu && fu->op() == unop::G)
if (f1 == constant::false_instance() &&
syntactic_implication(f2, fu->child()))
{
result_ = true;
return;
}
if (syntactic_implication(f2, f))
result_ = true;
return;
......
......@@ -121,8 +121,9 @@ namespace spot
{
if (!scc_computed_)
this->compute_scc();
this->prune_acc();
// FIXME
// this->delete_scc();
this->delete_scc();
}
std::string
......@@ -418,15 +419,33 @@ namespace spot
}
}
// FIXME
// Be careful, we have to stock on s2 the accepting condition on the arc
// leaving s1 (possible when the simulation is delayed). Since s2 simulate
// s1, s2 has some label whose implies these of s1, so we can put the
// accepting conditions on this arcs.
for (tgba_explicit::state::const_iterator j = s1->begin();
j != s1->end(); ++j)
{
// FIXME
transition* t = new transition();
t->dest = (*j)->dest;
t->condition = (*j)->condition;
t->acceptance_conditions = (*j)->acceptance_conditions;
const_cast<tgba_explicit::state*>(s2)->push_back(t);
}
// We remove all the predecessor of s1.
(i->second)->clear();
// then we can remove s1 safely, without change the language
// of the automaton.
// useless because the state is not reachable.
this->remove_state(sim1);
}
/////////////////////////////////////////
/////////////////////////////////////////
// From gtec.cc
......@@ -562,14 +581,145 @@ namespace spot
scc_computed_ = true;
}
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
void
tgba_reduc::delete_scc()
tgba_reduc::prune_acc()
{
if (!scc_computed_)
this->compute_scc();
Sgi::hash_map<int, const spot::state*>::iterator i;
for (i = state_scc_v_.begin(); i != state_scc_v_.end(); ++i)
{
if (is_not_accepting(i->second))
remove_acc(i->second);
}
}
void
tgba_reduc::remove_acc(const spot::state* s)
{
//std::cout << "remove_acc" << std::endl;
tgba_explicit::state* s1;
seen_map::iterator sm = si_.find(s);
sm = si_.find(s);
int n = sm->second;
for (sm == si_.begin(); sm != si_.end(); ++sm)
{
if (sm->second == n)
{
s1 = name_state_map_[tgba_explicit::format_state(s)];
s1 = const_cast<tgba_explicit::state*>(s1);
for (state::iterator i = s1->begin();
i != s1->end(); ++i)
(*i)->acceptance_conditions = bddfalse;
}
else
{
// FIXME
/*
tgba_succ_iterator* si = this->succ_iter(sm->first);
spot::state* s2 = si->current_state();
seen_map::iterator sm2 = si_.find(s2);
if (sm2->second == n)
{
s1 = name_state_map_[tgba_explicit::format_state(sm2->first)];
for (state::iterator i = s1->begin();
i != s1->end(); ++i)
(*i)->acceptance_conditions = bddfalse;
}
delete s2;
delete si;
*/
}
}
}
bool
tgba_reduc::is_not_accepting(const spot::state* s,
int n)
{
std::cout << "delete_scc" << std::endl;
//std::cout << "is not accepting" << std::endl;
bool b = false;
// First call of is_terminal //
seen_map::const_iterator i;
if (n == -1)
{
acc_ = bddfalse;
b = true;
assert(seen_ == 0);
seen_ = new seen_map();
i = si_.find(s);
assert(i->first != 0);
n = i->second;
}
///////////////////////////////
seen_map::const_iterator sm = seen_->find(s);
if (sm == seen_->end())
{
// this state is visited for the first time.
seen_->insert(std::pair<const spot::state*, int>(s, 1));
i = si_.find(s);
assert(i->first != 0);
if (n != i->second)
return true;
}
else
// This state is already visited.
{
delete s;
s = 0;
return true;
}
spot::state* s2;
tgba_succ_iterator* j = this->succ_iter(s);
for (j->first(); !j->done(); j->next())
{
s2 = j->current_state();
i = si_.find(s2);
assert(i->first != 0);
if (n == i->second)
{
acc_ |= j->current_acceptance_conditions();
this->is_not_accepting(s2, n);
}
}
delete j;
// First call of is_terminal //
if (b)
{
for (seen_map::iterator i = seen_->begin();
i != seen_->end(); ++i)
{
s2 = const_cast<spot::state*>(i->first);
assert(s2 != 0);
delete dynamic_cast<tgba_explicit*>(s2);
}
seen_->clear();
delete seen_;
seen_ = 0;
return acc_ != this->all_acceptance_conditions();
}
///////////////////////////////
return true;
}
void
tgba_reduc::delete_scc()
{
bool change = true;
Sgi::hash_map<int, const spot::state*>::iterator i;
//Sgi::hash_map<int, const spot::state*>::iterator itmp;
spot::state* s;
// we check if there is a terminal SCC we can be remove while
......@@ -580,21 +730,16 @@ namespace spot
change = false;
for (i = state_scc_v_.begin(); i != state_scc_v_.end(); ++i)
{
std::cout << "delete_scc : ["
<< this->format_state(i->second)
<< "]"
<< "is_terminal ??" << std::endl;
s = (i->second)->clone();
if (is_terminal(s))
{
change = true;
this->remove_scc(const_cast<spot::state*>(i->second));
remove_scc(const_cast<spot::state*>(i->second));
state_scc_v_.erase(i);
break;
}
//else
delete s;
std::cout << "end is_terminal" << std::endl;
}
}
}
......@@ -610,11 +755,6 @@ namespace spot
// So we can remove it safely without change the
// automaton language.
std::cout << "is_terminal : ["
<< this->format_state(s)
<< "]"
<< std::endl;
bool b = false;
// First call of is_terminal //
......@@ -631,25 +771,19 @@ namespace spot
}
///////////////////////////////
std::cout << "seen_->find" << std::endl;
seen_map::const_iterator sm = seen_->find(s);
std::cout << "seen_->end" << std::endl;
if (sm == seen_->end())
{
// this state is visited for the first time.
std::cout << "first time" << std::endl;
seen_->insert(std::pair<const spot::state*, int>(s, 1));
std::cout << "seen_->insert" << std::endl;
i = si_.find(s);
std::cout << "assert" << std::endl;
assert(i->first != 0);
if (n != i->second)
return false;
}
else
// This state is already visited.
{
std::cout << "second time" << std::endl;
// This state is already visited.
delete s;
s = 0;
return true;
......@@ -658,10 +792,8 @@ namespace spot
bool ret = true;
spot::state* s2;
tgba_succ_iterator* j = this->succ_iter(s);
int nb_succ = 0;
for (j->first(); !j->done(); j->next())
{
std::cout << "successor " << nb_succ++ << std::endl;
s2 = j->current_state();
acc_ |= j->current_acceptance_conditions();
ret &= this->is_terminal(s2, n);
......@@ -673,24 +805,18 @@ namespace spot
// First call of is_terminal //
if (b)
{
std::cout << "if b : begin" << std::endl;
for (seen_map::iterator i = seen_->begin();
i != seen_->end(); ++i)
{
std::cout << "delete" << std::endl;
s2 = const_cast<spot::state*>(i->first);
assert(s2 != 0);
delete dynamic_cast<tgba_explicit*>(s2);
}
seen_->clear();
std::cout << "delete seen_" << std::endl;
delete seen_;
std::cout << "seen_ = 0" << std::endl;
seen_ = 0;
std::cout << "acc_ == this->all_acceptance_conditions()" << std::endl;
if (acc_ == this->all_acceptance_conditions())
ret = false;
std::cout << "if b : end" << nb_succ << std::endl;
}
///////////////////////////////
......@@ -702,8 +828,6 @@ namespace spot
{
// To remove a scc, we remove all his state.
std::cout << "remove_scc" << std::endl;
seen_map::iterator sm = si_.find(s);
sm = si_.find(s);
int n = sm->second;
......
......@@ -55,6 +55,9 @@ namespace spot
/// Remove all state which not lead to an accepting cycle.
void prune_scc();
/// Remove some useless accepting condition.
void prune_acc();
/// Compute the maximal SCC of the automata.
void compute_scc();
......@@ -82,6 +85,7 @@ namespace spot
ptr_hash<tgba_explicit::state> > sp_map;
sp_map state_predecessor_map_;
// For reduction using scc.
typedef Sgi::hash_map<const spot::state*, int,
state_ptr_hash, state_ptr_equal> seen_map;
seen_map si_;
......@@ -147,14 +151,23 @@ namespace spot
bool is_terminal(const spot::state* s,
int n = -1);
/// For compute_scc.
void remove_component(const spot::state* from);
// Return false if the scc contains all the accepting condition.
bool is_not_accepting(const spot::state* s,
int n = -1);
/// If a scc maximal do not contains all the accepting condition
/// we can remove all the accepting condition in this scc.
void remove_acc(const spot::state* s);
/// Remove all the state which belong to the same scc that s.
void remove_scc(spot::state* s);
/// Same as remove_scc but more efficient.
void remove_scc_depth_first(spot::state* s, int n = -1);
/// For compute_scc.
void remove_component(const spot::state* from);
};
}
......
......@@ -54,12 +54,14 @@ namespace spot
bool exist = false;
for (sn_v::iterator i = lnode_succ->begin();
i != lnode_succ->end(); ++i)
if ((*i)->compare(n) == true)
if ((*i == n) ||
((*i)->compare(n) == true))
exist = true;
if (exist)
return false;
lnode_succ->push_back(n);
n->add_pred(this);
return true;
}
......@@ -81,13 +83,16 @@ namespace spot
void
spoiler_node::add_pred(spoiler_node* n)
{
bool exist = false;
for (sn_v::iterator i = lnode_pred->begin();
i != lnode_pred->end(); ++i)
lnode_pred->push_back(n);
/*
bool exist = false;
for (sn_v::iterator i = lnode_pred->begin();
i != lnode_pred->end(); ++i)
if ((*i)->compare(n) == 0)
exist = true;
if (!exist)
exist = true;
if (!exist)
lnode_pred->push_back(n);
*/
}
void
......@@ -98,6 +103,24 @@ namespace spot
(*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;
}
if (change != not_win)
for (Sgi::vector<spoiler_node*>::iterator i = lnode_pred->begin();
i != lnode_pred->end(); ++i)
(*i)->set_win();
return change != not_win;
}
/*
bool
spoiler_node::set_win()
{
......@@ -109,6 +132,7 @@ namespace spot
}
return change != not_win;
}
*/
std::string