Revamp the multop interface to allow some basic optimizations like

not constructing a single-child multop.
* src/ltlast/multop.hh (multop::instance(type)): Remove.
(multop::instance(type, formula*, formula*)): Return a formula*.
(multop::instance(type, vec*)): Make it public and return a formula*.
(multop::add_sorted, multop::add):
* src/ltlast/multop.cc (multop::instance(type, vec*)): Rewrite.
(multop::instance(type)): Delete.
(multop::instance(type, formula*, formula*)): Adjust.
(multop::add_sorted, multop::add): Remove.
* src/ltlvisit/clone.cc (clone_visitor::visit(multop*)) Adjust.
* src/ltlvisit/nenoform.cc
(negative_normal_form_visitor::::visit(multop*)) Adjust.
* src/ltltest/equals.test: Make sure `a & a' and `a' are equals.
* wrap/python/tests/ltlsimple.py: Adjust.
This commit is contained in:
Alexandre Duret-Lutz 2003-08-10 16:29:49 +00:00
parent 317fed597b
commit de6314ed74
8 changed files with 123 additions and 98 deletions

View file

@ -1,6 +1,8 @@
#include <cassert>
#include <utility>
#include <algorithm>
#include "multop.hh"
#include "constant.hh"
#include "visitor.hh"
#include "ltlvisit/destroy.hh"
@ -77,10 +79,78 @@ namespace spot
multop::map multop::instances;
multop*
formula*
multop::instance(type op, vec* v)
{
pair p(op, v);
// Inline children of same kind.
{
vec inlined;
vec::iterator i = v->begin();
while (i != v->end())
{
multop* p = dynamic_cast<multop*>(*i);
if (p && p->op() == op)
{
unsigned ps = p->size();
for (unsigned n = 0; n < ps; ++n)
inlined.push_back(p->nth(n));
// That sub-formula is now useless, drop it.
// Note that we use unref(), not destroy(), because we've
// adopted its children and don't want to destroy these.
formula::unref(*i);
i = v->erase(i);
}
else
{
++i;
}
}
v->insert(v->end(), inlined.begin(), inlined.end());
}
std::sort(v->begin(), v->end());
// Remove duplicates. We can't use std::unique(), because we
// must destroy() any formula we drop.
{
formula* last = 0;
vec::iterator i = v->begin();
while (i != v->end())
{
if (*i == last)
{
destroy(*i);
i = v->erase(i);
}
else
{
last = *i++;
}
}
}
if (v->size() == 0)
{
delete v;
switch (op)
{
case And:
return constant::true_instance();
case Or:
return constant::false_instance();
}
/* Unreachable code. */
assert(0);
}
if (v->size() == 1)
{
formula* res = (*v)[0];
delete v;
return res;
}
map::iterator i = instances.find(p);
if (i != instances.end())
{
@ -93,75 +163,15 @@ namespace spot
}
multop*
multop::instance(type op)
{
return instance(op, new vec);
}
multop*
formula*
multop::instance(type op, formula* first, formula* second)
{
vec* v = new vec;
multop::add(op, v, first);
multop::add(op, v, second);
v->push_back(first);
v->push_back(second);
return instance(op, v);
}
void
multop::add_sorted(vec* v, formula* f)
{
// Keep V sorted. When adding a new multop, iterate over all
// element until we find either an identical element, or the
// place where the new one should be inserted.
vec::iterator i;
for (i = v->begin(); i != v->end(); ++i)
{
if (*i > f)
break;
if (*i == f)
{
// F is already a child. Drop it.
destroy(f);
return;
}
}
v->insert(i, f);
}
multop::vec*
multop::add(type op, vec* v, formula* f)
{
// If the formula we add is itself a multop for the same operator,
// merge its children.
multop* p = dynamic_cast<multop*>(f);
if (p && p->op() == op)
{
unsigned ps = p->size();
for (unsigned i = 0; i < ps; ++i)
add_sorted(v, p->nth(i));
// That sub-formula is now useless, drop it.
// Note that we use unref(), not destroy(), because we've
// adopted its children and don't want to destroy these.
formula::unref(f);
}
else
{
add_sorted(v, f);
}
return v;
}
void
multop::add(multop** m, formula* f)
{
vec* v = new vec(*(*m)->children_);
type op = (*m)->op();
multop::add(op, v, f);
formula::unref(*m);
*m = instance(op, v);
}
unsigned
multop::instance_count()
{