spot/src/tgba/bdddict.cc
Alexandre Duret-Lutz c4a5b325a2 * src/sanity/style.test: New file.
* src/sanity/Makefile.am (check-local): Run it.
* src/ltlvisit/nenoform.cc, src/ltlvisit/tostring.cc,
src/tgba/bdddict.cc, src/tgba/bddprint.cc, src/tgba/tgba.cc,
src/tgba/tgbaproduct.cc, src/tgbaalgos/lbtt.cc,
src/tgbaalgos/magic.cc, src/tgbaalgos/powerset.cc,
src/tgbaalgos/reachiter.cc, src/tgbaalgos/gtec/ce.cc,
src/tgbaalgos/gtec/gtec.cc, src/tgbatest/ltl2tgba.cc: Fix style
issues reported by style.test.
2004-05-10 18:38:20 +00:00

389 lines
9.6 KiB
C++

// Copyright (C) 2003, 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 <ltlvisit/clone.hh>
#include <ltlvisit/destroy.hh>
#include <ltlvisit/tostring.hh>
#include <cassert>
#include "bdddict.hh"
namespace spot
{
bdd_dict::bdd_dict()
: bdd_allocator(),
next_to_now(bdd_newpair()),
now_to_next(bdd_newpair())
{
free_annonymous_list_of[0] = annon_free_list(this);
}
bdd_dict::~bdd_dict()
{
assert_emptiness();
bdd_freepair(next_to_now);
bdd_freepair(now_to_next);
}
int
bdd_dict::register_proposition(const ltl::formula* f, const void* for_me)
{
int num;
// Do not build a variable that already exists.
fv_map::iterator sii = var_map.find(f);
if (sii != var_map.end())
{
num = sii->second;
}
else
{
f = clone(f);
num = allocate_variables(1);
var_map[f] = num;
var_formula_map[num] = f;
}
var_refs[num].insert(for_me);
return num;
}
void
bdd_dict::register_propositions(bdd f, const void* for_me)
{
if (f == bddtrue || f == bddfalse)
return;
vf_map::iterator i = var_formula_map.find(bdd_var(f));
assert(i != var_formula_map.end());
var_refs[i->first].insert(for_me);
register_propositions(bdd_high(f), for_me);
register_propositions(bdd_low(f), for_me);
}
int
bdd_dict::register_state(const ltl::formula* f, const void* for_me)
{
int num;
// Do not build a state that already exists.
fv_map::iterator sii = now_map.find(f);
if (sii != now_map.end())
{
num = sii->second;
}
else
{
f = ltl::clone(f);
num = allocate_variables(2);
now_map[f] = num;
now_formula_map[num] = f;
// Record that num+1 should be renamed as num when
// the next state becomes current.
bdd_setpair(next_to_now, num + 1, num);
bdd_setpair(now_to_next, num, num + 1);
}
var_refs[num].insert(for_me);
return num;
}
int
bdd_dict::register_acceptance_variable(const ltl::formula* f,
const void* for_me)
{
int num;
// Do not build an acceptance variable that already exists.
fv_map::iterator sii = acc_map.find(f);
if (sii != acc_map.end())
{
num = sii->second;
}
else
{
f = clone(f);
num = allocate_variables(1);
acc_map[f] = num;
acc_formula_map[num] = f;
}
var_refs[num].insert(for_me);
return num;
}
void
bdd_dict::register_acceptance_variables(bdd f, const void* for_me)
{
if (f == bddtrue || f == bddfalse)
return;
vf_map::iterator i = acc_formula_map.find(bdd_var(f));
assert(i != acc_formula_map.end());
var_refs[i->first].insert(for_me);
register_acceptance_variables(bdd_high(f), for_me);
register_acceptance_variables(bdd_low(f), for_me);
}
int
bdd_dict::register_anonymous_variables(int n, const void* for_me)
{
free_annonymous_list_of_type::iterator i =
free_annonymous_list_of.find(for_me);
if (i == free_annonymous_list_of.end())
{
typedef free_annonymous_list_of_type fal;
i = (free_annonymous_list_of.insert
(fal::value_type(for_me, free_annonymous_list_of[0]))).first;
}
int res = i->second.register_n(n);
while (n--)
var_refs[res + n].insert(for_me);
return res;
}
void
bdd_dict::register_all_variables_of(const void* from_other,
const void* for_me)
{
vr_map::iterator i;
for (i = var_refs.begin(); i != var_refs.end(); ++i)
{
ref_set& s = i->second;
if (s.find(from_other) != s.end())
s.insert(for_me);
}
free_annonymous_list_of[for_me] = free_annonymous_list_of[from_other];
}
void
bdd_dict::unregister_variable(int var, const void* me)
{
vr_map::iterator i = var_refs.find(var);
assert(i != var_refs.end());
unregister_variable(i, me);
}
void
bdd_dict::unregister_variable(vr_map::iterator& cur, const void* me)
{
ref_set& s = cur->second;
ref_set::iterator si = s.find(me);
if (si == s.end())
return;
s.erase(si);
if (!s.empty())
return;
// ME was the last user of this variable.
// Let's free it. First, we need to find
// if this is a Now, a Var, or an Acc variable.
int var = cur->first;
int n = 1;
const ltl::formula* f = 0;
vf_map::iterator vi = var_formula_map.find(var);
if (vi != var_formula_map.end())
{
f = vi->second;
var_map.erase(f);
var_formula_map.erase(vi);
}
else
{
vi = now_formula_map.find(var);
if (vi != now_formula_map.end())
{
f = vi->second;
now_map.erase(f);
now_formula_map.erase(vi);
n = 2;
bdd_setpair(next_to_now, var + 1, var + 1);
bdd_setpair(now_to_next, var, var);
}
else
{
vi = acc_formula_map.find(var);
if (vi != acc_formula_map.end())
{
f = vi->second;
acc_map.erase(f);
acc_formula_map.erase(vi);
}
else
{
free_annonymous_list_of_type::iterator i;
for (i = free_annonymous_list_of.begin();
i != free_annonymous_list_of.end(); ++i)
i->second.remove(var, n);
}
}
}
// Actually release the associated BDD variables, and the
// formula itself.
release_variables(var, n);
if (f)
ltl::destroy(f);
var_refs.erase(cur);
}
void
bdd_dict::unregister_all_my_variables(const void* me)
{
vr_map::iterator i;
for (i = var_refs.begin(); i != var_refs.end();)
{
// Increment i++ now, we will possibly erase
// the current node (which would invalidate the iterator).
vr_map::iterator cur = i++;
unregister_variable(cur, me);
}
free_annonymous_list_of.erase(me);
}
bool
bdd_dict::is_registered_proposition(const ltl::formula* f, const void* by_me)
{
fv_map::iterator fi = var_map.find(f);
if (fi == var_map.end())
return false;
ref_set& s = var_refs[fi->second];
return s.find(by_me) != s.end();
}
bool
bdd_dict::is_registered_state(const ltl::formula* f, const void* by_me)
{
fv_map::iterator fi = now_map.find(f);
if (fi == now_map.end())
return false;
ref_set& s = var_refs[fi->second];
return s.find(by_me) != s.end();
}
bool
bdd_dict::is_registered_acceptance_variable(const ltl::formula* f,
const void* by_me)
{
fv_map::iterator fi = acc_map.find(f);
if (fi == acc_map.end())
return false;
ref_set& s = var_refs[fi->second];
return s.find(by_me) != s.end();
}
std::ostream&
bdd_dict::dump(std::ostream& os) const
{
fv_map::const_iterator fi;
os << "Atomic Propositions:" << std::endl;
for (fi = var_map.begin(); fi != var_map.end(); ++fi)
{
os << " " << fi->second << " (x"
<< var_refs.find(fi->second)->second.size() << "): ";
to_string(fi->first, os) << std::endl;
}
os << "States:" << std::endl;
for (fi = now_map.begin(); fi != now_map.end(); ++fi)
{
int refs = var_refs.find(fi->second)->second.size();
os << " " << fi->second << " (x" << refs << "): Now[";
to_string(fi->first, os) << "]" << std::endl;
os << " " << fi->second + 1 << " (x" << refs << "): Next[";
to_string(fi->first, os) << "]" << std::endl;
}
os << "Accepting Conditions:" << std::endl;
for (fi = acc_map.begin(); fi != acc_map.end(); ++fi)
{
os << " " << fi->second << " (x"
<< var_refs.find(fi->second)->second.size() << "): Acc[";
to_string(fi->first, os) << "]" << std::endl;
}
os << "Free list:" << std::endl;
dump_free_list(os);
os << std::endl;
return os;
}
void
bdd_dict::assert_emptiness() const
{
bool fail = false;
if (var_map.empty()
&& now_map.empty()
&& acc_map.empty())
{
if (!var_formula_map.empty())
{
std::cerr << "var_map is empty but var_formula_map is not"
<< std::endl;
fail = true;
}
if (!now_formula_map.empty())
{
std::cerr << "now_map is empty but now_formula_map is not"
<< std::endl;
fail = true;
}
if (!acc_formula_map.empty())
{
std::cerr << "acc_map is empty but acc_formula_map is not"
<< std::endl;
fail = true;
}
if (!var_refs.empty())
{
std::cerr << "maps are empty but var_refs is not" << std::endl;
fail = true;
vr_map::const_iterator i;
for (i = var_refs.begin(); i != var_refs.end(); ++i)
std::cerr << " " << i->first << ":" << i->second.size();
std::cerr << std::endl;
}
if (!fail)
return;
}
else
{
std::cerr << "some maps are not empty" << std::endl;
}
dump(std::cerr);
assert(0);
}
bdd_dict::annon_free_list::annon_free_list(bdd_dict* d)
: dict_(d)
{
}
int
bdd_dict::annon_free_list::extend(int n)
{
assert(dict_);
int b = dict_->allocate_variables(n);
free_annonymous_list_of_type::iterator i;
for (i = dict_->free_annonymous_list_of.begin();
i != dict_->free_annonymous_list_of.end(); ++i)
if (&i->second != this)
i->second.insert(b, n);
return b;
}
}