spot/src/tgbaalgos/tarjan_on_fly.cc
Alexandre Duret-Lutz 3f2cba6304 * src/sanity/style.test: Suggest ++i over i++ when it does not
matter, for consistency.
* src/tgbaalgos/tarjan_on_fly.cc, iface/gspn/ssp.cc,
src/tgbaalgos/reductgba_sim_del.cc, src/tgbaalgos/reductgba_sim.cc,
src/tgbaalgos/minimalce.cc, src/tgba/tgbareduc.cc: Adjust.
2004-09-23 12:20:10 +00:00

242 lines
4.6 KiB
C++

// 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 "tgbaalgos/tarjan_on_fly.hh"
namespace spot
{
tarjan_on_fly::tarjan_on_fly(const tgba_tba_proxy *a)
: a(a), x(0)
{
}
tarjan_on_fly::~tarjan_on_fly()
{
for (stack_type::iterator i = stack.begin();
i != stack.end(); ++i)
{
//if ((*i).s)
hash_type::iterator hi = h.find(i->s);
if (hi != h.end())
h.erase(hi);
delete (*i).s;
//if ((*i).lasttr)
delete (*i).lasttr;
}
for (hash_type::iterator i = h.begin();
i != h.end();)
{
const state *s = i->first;
++i;
delete s;
}
}
ce::counter_example*
tarjan_on_fly::check()
{
tgba_succ_iterator* iter = 0;
const state* succ = 0;
int pos = 0;
top = dftop = -1;
violation = false;
const state* s = a->get_init_state();
push(s);
while (!violation && dftop >= 0)
{
s = stack[dftop].s;
iter = stack[dftop].lasttr;
if (iter == 0)
{
iter = a->succ_iter(s);
iter->first();
stack[dftop].lasttr = iter;
}
else
{
iter->next();
}
succ = 0;
if (!iter->done())
{
succ = iter->current_state();
if (h.find(succ) == h.end())
push(succ);
else
{
pos = in_stack(succ);
delete succ;
if (pos != -1) // succ is in stack
lowlinkupdate(dftop, pos);
}
}
else
pop();
}
if (violation)
return build_counter();
//std::cout << "NO COUNTER EXAMPLE FOUND" << std::endl;
return 0;
}
void
tarjan_on_fly::push(const state* s)
{
h[s] = top++;
struct_state ss = { s, 0, top, dftop, 0 };
if (a->state_is_accepting(s))
{
ss.acc = top;
x = s; // FIXME
}
else if (dftop >= 0)
ss.acc = stack[dftop].acc;
else
ss.acc = -1;
if (top < (int)stack.size())
{
const state* sdel = stack[top].s;
tgba_succ_iterator* iter = stack[top].lasttr;
if (h.find(sdel) == h.end())
{
assert(0);
delete sdel;
}
if (iter)
delete iter;
stack[top] = ss;
}
else
{
stack.push_back(ss);
}
dftop = top;
}
void
tarjan_on_fly::pop()
{
/*
const state *s = stack[dftop].s;
hash_type::iterator hi = h.find(s);
hi->second = -1;
*/
int p = stack[dftop].pre;
if (p >= 0)
lowlinkupdate(p, dftop);
if (stack[dftop].lowlink == dftop)
top = dftop - 1;
dftop = p;
}
void
tarjan_on_fly::lowlinkupdate(int f, int t)
{
if (stack[t].lowlink <= stack[f].lowlink)
{
if (stack[t].lowlink <= stack[f].acc)
{
violation = true;
}
stack[f].lowlink = stack[t].lowlink;
}
}
int
tarjan_on_fly::in_stack(const state* s) const
{
int n = 0;
/*
hash_type::const_iterator hi = h.find(s);
if (hi != h.end())
n = hi->second;
else
n = -1;
*/
stack_type::const_iterator i;
for (i = stack.begin(); i != stack.end(); ++i, ++n)
if (s->compare((*i).s) == 0)
break;
if (i == stack.end())
return -1;
return n;
}
ce::counter_example*
tarjan_on_fly::build_counter()
{
ce = new ce::counter_example(a);
stack_type::iterator i;
for (i = stack.begin(); i != stack.end(); ++i)
{
if (x && x->compare((*i).s) == 0)
break;
ce->prefix.push_back(ce::state_ce((*i).s->clone(),
(*i).lasttr->current_condition()));
}
for (; i != stack.end(); ++i)
{
ce->cycle.push_back(ce::state_ce((*i).s->clone(),
(*i).lasttr->current_condition()));
}
return ce;
}
std::ostream&
tarjan_on_fly::print_stat(std::ostream& os) const
{
int ce_size = 0;
if (ce)
ce_size = ce->size();
os << "Size of Counter Example : " << ce_size << std::endl
<< "States explored : " << h.size() << std::endl;
return os;
}
}