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:
parent
317fed597b
commit
de6314ed74
8 changed files with 123 additions and 98 deletions
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue