snf: Fix the handling of bounded repetition.

star_normal_form() used to be called under bounded
repetitions like [*0..4], but some of these rewritings
are only correct for [*0..].  For instance
     (a*|1)[*]      can be rewritten to    1[*]
but  (a*|1)[*0..1]  cannot be rewritten to 1[*0..1]
it would be correct to rewrite the latter as (a[+]|1)[*0..1],
canceling the empty word in a*.

Also (a*;b*)[*]     can be rewritten to    (a|b)[*]
but  (a*;b*)[*0..1]  cannot be rewritten to (a|b)[*0..1]
and it cannot either be rewritten to (a[+]|b[+])[*0..1].

This patch introduces a new function to implement
rewritings under bounded repetition.

* src/ltlvisit/snf.hh, src/ltlvisit/snf.cc (star_normal_form_unbounded):
New function.
* src/ltlvisit/simplify.cc: Use it.
* src/ltltest/reduccmp.test: Add tests.
* doc/tl/tl.tex: Document the rewritings implemented.
This commit is contained in:
Alexandre Duret-Lutz 2014-05-15 20:06:43 +02:00
parent 53de8fc3a4
commit 05ed3def00
5 changed files with 112 additions and 21 deletions

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2012 Laboratoire de Recherche et Developpement
// Copyright (C) 2012, 2014 Laboratoire de Recherche et Developpement
// de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -31,6 +31,7 @@ namespace spot
// E°
class snf_visitor: public visitor
{
protected:
const formula* result_;
snf_cache* cache_;
public:
@ -144,21 +145,50 @@ namespace spot
if (!f->accepts_eword())
return f->clone();
if (cache_)
{
snf_cache::const_iterator i = cache_->find(f);
if (i != cache_->end())
return i->second->clone();
}
snf_cache::const_iterator i = cache_->find(f);
if (i != cache_->end())
return i->second->clone();
f->accept(*this);
if (cache_)
(*cache_)[f->clone()] = result_->clone();
(*cache_)[f->clone()] = result_->clone();
return result_;
}
};
// E^□
class snf_visitor_bounded: public snf_visitor
{
public:
snf_visitor_bounded(snf_cache* c): snf_visitor(c)
{
}
void
visit(const bunop* bo)
{
bunop::type op = bo->op();
switch (op)
{
case bunop::Star:
assert(bo->accepts_eword());
result_ = bunop::instance(bunop::Star,
recurse(bo->child()),
std::max(bo->min(), 1U),
bo->max());
break;
}
}
void
visit(const multop* mo)
{
if (mo->op() == multop::Concat)
result_ = mo->clone();
else
this->snf_visitor::visit(mo);
}
};
}
@ -169,5 +199,12 @@ namespace spot
return v.recurse(sere);
}
const formula*
star_normal_form_bounded(const formula* sere, snf_cache* cache)
{
snf_visitor_bounded v(cache);
return v.recurse(sere);
}
}
}