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:
parent
53de8fc3a4
commit
05ed3def00
5 changed files with 112 additions and 21 deletions
|
|
@ -106,6 +106,16 @@ namespace spot
|
|||
old->first->destroy();
|
||||
}
|
||||
}
|
||||
{
|
||||
snf_cache::iterator i = snfb_cache_.begin();
|
||||
snf_cache::iterator end = snfb_cache_.end();
|
||||
while (i != end)
|
||||
{
|
||||
snf_cache::iterator old = i++;
|
||||
old->second->destroy();
|
||||
old->first->destroy();
|
||||
}
|
||||
}
|
||||
{
|
||||
f2f_map::iterator i = bool_isop_.begin();
|
||||
f2f_map::iterator end = bool_isop_.end();
|
||||
|
|
@ -387,6 +397,13 @@ namespace spot
|
|||
return ltl::star_normal_form(f, &snf_cache_);
|
||||
}
|
||||
|
||||
const formula*
|
||||
star_normal_form_bounded(const formula* f)
|
||||
{
|
||||
return ltl::star_normal_form_bounded(f, &snfb_cache_);
|
||||
}
|
||||
|
||||
|
||||
const formula*
|
||||
boolean_to_isop(const formula* f)
|
||||
{
|
||||
|
|
@ -406,6 +423,7 @@ namespace spot
|
|||
f2f_map nenoform_;
|
||||
syntimpl_cache_t syntimpl_;
|
||||
snf_cache snf_cache_;
|
||||
snf_cache snfb_cache_;
|
||||
f2f_map bool_isop_;
|
||||
};
|
||||
|
||||
|
|
@ -1080,7 +1098,10 @@ namespace spot
|
|||
min = 0;
|
||||
if (min == 0)
|
||||
{
|
||||
const formula* s = c_->star_normal_form(h);
|
||||
const formula* s =
|
||||
bo->max() == bunop::unbounded ?
|
||||
c_->star_normal_form(h) :
|
||||
c_->star_normal_form_bounded(h);
|
||||
h->destroy();
|
||||
h = s;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2012, 2013 Laboratoire de Recherche et Developpement
|
||||
// de l'Epita (LRDE).
|
||||
// Copyright (C) 2012, 2013, 2014 Laboratoire de Recherche et
|
||||
// Developpement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -52,6 +52,10 @@ namespace spot
|
|||
/// \param cache an optional cache
|
||||
SPOT_API const formula*
|
||||
star_normal_form(const formula* sere, snf_cache* cache = 0);
|
||||
|
||||
/// A variant of star_normal_form() for r[*0..j] where j < ω.
|
||||
SPOT_API const formula*
|
||||
star_normal_form_bounded(const formula* sere, snf_cache* cache = 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue