Commit 0f11e5fe authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

Speedup mark_concat_ops() and simplify_mark() with a cache.

* src/ltlvisit/mark.hh, src/ltlvisit/mark.cc (mark_concat_ops,
simplify_mark): Rewrite these two functions as methods of
(mark_tools): this new class.
* src/ltlast/binop.cc, src/ltlast/unop.cc: Adjust computation
of not_marked to ignore marked operators that are not at
the top-level.  I.e., something like X(!{a}) is not marked.
* src/tgbaalgos/ltl2tgba_fm.cc (translate_dict::mt): New
instance of mark_tools.
(formula_canonizer::translate) Adjust calls to
mark_concat_ops() and simplify_mark().
parent f68f639e
...@@ -106,9 +106,8 @@ namespace spot ...@@ -106,9 +106,8 @@ namespace spot
is.accepting_eword = false; is.accepting_eword = false;
break; break;
case EConcatMarked: case EConcatMarked:
is.not_marked = false;
// fall through
case EConcat: case EConcat:
is.not_marked = (op != EConcatMarked);
is.ltl_formula = false; is.ltl_formula = false;
is.boolean = false; is.boolean = false;
is.eltl_formula = false; is.eltl_formula = false;
...@@ -130,11 +129,11 @@ namespace spot ...@@ -130,11 +129,11 @@ namespace spot
is.syntactic_obligation = second->is_syntactic_guarantee(); is.syntactic_obligation = second->is_syntactic_guarantee();
is.syntactic_recurrence = second->is_syntactic_guarantee(); is.syntactic_recurrence = second->is_syntactic_guarantee();
} }
assert(first->is_sere_formula()); assert(first->is_sere_formula());
assert(second->is_psl_formula()); assert(second->is_psl_formula());
break; break;
case UConcat: case UConcat:
is.not_marked = true;
is.ltl_formula = false; is.ltl_formula = false;
is.boolean = false; is.boolean = false;
is.eltl_formula = false; is.eltl_formula = false;
...@@ -156,11 +155,11 @@ namespace spot ...@@ -156,11 +155,11 @@ namespace spot
is.syntactic_obligation = second->is_syntactic_safety(); is.syntactic_obligation = second->is_syntactic_safety();
is.syntactic_persistence = second->is_syntactic_safety(); is.syntactic_persistence = second->is_syntactic_safety();
} }
assert(first->is_sere_formula()); assert(first->is_sere_formula());
assert(second->is_psl_formula()); assert(second->is_psl_formula());
break; break;
case U: case U:
is.not_marked = true;
// f U g is universal if g is eventual, or if f == 1. // f U g is universal if g is eventual, or if f == 1.
is.eventual = second->is_eventual(); is.eventual = second->is_eventual();
is.eventual |= (first == constant::true_instance()); is.eventual |= (first == constant::true_instance());
...@@ -181,6 +180,7 @@ namespace spot ...@@ -181,6 +180,7 @@ namespace spot
// is.syntactic_persistence = Persistence U Persistance // is.syntactic_persistence = Persistence U Persistance
break; break;
case W: case W:
is.not_marked = true;
// f W g is universal if f and g are, or if g == 0. // f W g is universal if f and g are, or if g == 0.
is.universal |= (second == constant::false_instance()); is.universal |= (second == constant::false_instance());
is.boolean = false; is.boolean = false;
...@@ -200,6 +200,7 @@ namespace spot ...@@ -200,6 +200,7 @@ namespace spot
break; break;
case R: case R:
is.not_marked = true;
// g R f is universal if f is universal, or if g == 0. // g R f is universal if f is universal, or if g == 0.
is.universal = second->is_universal(); is.universal = second->is_universal();
is.universal |= (first == constant::false_instance()); is.universal |= (first == constant::false_instance());
...@@ -220,6 +221,7 @@ namespace spot ...@@ -220,6 +221,7 @@ namespace spot
break; break;
case M: case M:
is.not_marked = true;
// g M f is eventual if both g and f are eventual, or if f == 1. // g M f is eventual if both g and f are eventual, or if f == 1.
is.eventual |= (second == constant::true_instance()); is.eventual |= (second == constant::true_instance());
is.boolean = false; is.boolean = false;
......
...@@ -39,6 +39,7 @@ namespace spot ...@@ -39,6 +39,7 @@ namespace spot
switch (op) switch (op)
{ {
case Not: case Not:
is.not_marked = true;
is.eventual = child->is_universal(); is.eventual = child->is_universal();
is.universal = child->is_eventual(); is.universal = child->is_eventual();
is.in_nenoform = (child->kind() == AtomicProp); is.in_nenoform = (child->kind() == AtomicProp);
...@@ -53,6 +54,7 @@ namespace spot ...@@ -53,6 +54,7 @@ namespace spot
is.accepting_eword = false; is.accepting_eword = false;
break; break;
case X: case X:
is.not_marked = true;
is.boolean = false; is.boolean = false;
is.X_free = false; is.X_free = false;
is.eltl_formula = false; is.eltl_formula = false;
...@@ -65,6 +67,7 @@ namespace spot ...@@ -65,6 +67,7 @@ namespace spot
is.accepting_eword = false; is.accepting_eword = false;
break; break;
case F: case F:
is.not_marked = true;
is.boolean = false; is.boolean = false;
is.eltl_formula = false; is.eltl_formula = false;
is.sere_formula = false; is.sere_formula = false;
...@@ -79,6 +82,7 @@ namespace spot ...@@ -79,6 +82,7 @@ namespace spot
is.accepting_eword = false; is.accepting_eword = false;
break; break;
case G: case G:
is.not_marked = true;
is.boolean = false; is.boolean = false;
is.eltl_formula = false; is.eltl_formula = false;
is.sere_formula = false; is.sere_formula = false;
...@@ -93,6 +97,7 @@ namespace spot ...@@ -93,6 +97,7 @@ namespace spot
is.accepting_eword = false; is.accepting_eword = false;
break; break;
case Finish: case Finish:
is.not_marked = true;
is.boolean = false; is.boolean = false;
is.ltl_formula = false; is.ltl_formula = false;
is.psl_formula = false; is.psl_formula = false;
...@@ -120,6 +125,7 @@ namespace spot ...@@ -120,6 +125,7 @@ namespace spot
is.accepting_eword = false; is.accepting_eword = false;
break; break;
case Closure: case Closure:
is.not_marked = true;
is.boolean = false; is.boolean = false;
is.ltl_formula = false; is.ltl_formula = false;
is.eltl_formula = false; is.eltl_formula = false;
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "ltlast/allnodes.hh" #include "ltlast/allnodes.hh"
#include <cassert> #include <cassert>
#include <algorithm> #include <algorithm>
#include "ltlvisit/tostring.hh"
#include "misc/casts.hh"
namespace spot namespace spot
{ {
...@@ -32,11 +34,11 @@ namespace spot ...@@ -32,11 +34,11 @@ namespace spot
class simplify_mark_visitor : public visitor class simplify_mark_visitor : public visitor
{ {
formula* result_; formula* result_;
bool has_mark_; mark_tools* tools_;
public: public:
simplify_mark_visitor() simplify_mark_visitor(mark_tools* t)
: has_mark_(false) : tools_(t)
{ {
} }
...@@ -50,12 +52,6 @@ namespace spot ...@@ -50,12 +52,6 @@ namespace spot
return result_; return result_;
} }
bool
has_mark()
{
return has_mark_;
}
void void
visit(atomic_prop* ao) visit(atomic_prop* ao)
{ {
...@@ -77,22 +73,7 @@ namespace spot ...@@ -77,22 +73,7 @@ namespace spot
void void
visit(unop* uo) visit(unop* uo)
{ {
switch (uo->op()) result_ = uo->clone();
{
case unop::NegClosure:
has_mark_ = true;
/* fall through */
case unop::Finish:
case unop::Closure:
case unop::Not:
case unop::X:
case unop::F:
case unop::G:
result_ = uo->clone();
return;
}
/* Unreachable code. */
assert(0);
} }
void void
...@@ -150,7 +131,6 @@ namespace spot ...@@ -150,7 +131,6 @@ namespace spot
case binop::EConcatMarked: case binop::EConcatMarked:
EMpairs.insert(std::make_pair(bo->first(), EMpairs.insert(std::make_pair(bo->first(),
bo->second())); bo->second()));
has_mark_ = true;
break; break;
} }
} }
...@@ -174,33 +154,13 @@ namespace spot ...@@ -174,33 +154,13 @@ namespace spot
void void
visit(binop* bo) visit(binop* bo)
{ {
switch (bo->op()) result_ = bo->clone();
{
case binop::EConcatMarked:
has_mark_ = true;
/* fall through */
case binop::Xor:
case binop::Implies:
case binop::Equiv:
case binop::U:
case binop::W:
case binop::M:
case binop::R:
case binop::EConcat:
case binop::UConcat:
result_ = bo->clone();
return;
}
/* Unreachable code. */
assert(0);
} }
formula* formula*
recurse(const formula* f) recurse(formula* f)
{ {
formula* g = f->clone(); return tools_->simplify_mark(f);
has_mark_ |= simplify_mark(g);
return g;
} }
}; };
...@@ -208,8 +168,11 @@ namespace spot ...@@ -208,8 +168,11 @@ namespace spot
class mark_visitor : public visitor class mark_visitor : public visitor
{ {
formula* result_; formula* result_;
mark_tools* tools_;
public: public:
mark_visitor() mark_visitor(mark_tools* t)
: tools_(t)
{ {
} }
~mark_visitor() ~mark_visitor()
...@@ -294,28 +257,74 @@ namespace spot ...@@ -294,28 +257,74 @@ namespace spot
formula* formula*
recurse(formula* f) recurse(formula* f)
{ {
return mark_concat_ops(f); return tools_->mark_concat_ops(f);
} }
}; };
} }
mark_tools::mark_tools()
: simpvisitor_(new simplify_mark_visitor(this)),
markvisitor_(new mark_visitor(this))
{
}
mark_tools::~mark_tools()
{
delete simpvisitor_;
delete markvisitor_;
{
f2f_map::iterator i = simpmark_.begin();
f2f_map::iterator end = simpmark_.end();
while (i != end)
{
f2f_map::iterator old = i++;
old->second->destroy();
old->first->destroy();
}
}
{
f2f_map::iterator i = markops_.begin();
f2f_map::iterator end = markops_.end();
while (i != end)
{
f2f_map::iterator old = i++;
old->second->destroy();
old->first->destroy();
}
}
}
formula* formula*
mark_concat_ops(const formula* f) mark_tools::mark_concat_ops(const formula* f)
{ {
mark_visitor v; f2f_map::iterator i = markops_.find(f);
const_cast<formula*>(f)->accept(v); if (i != markops_.end())
return v.result(); return i->second->clone();
const_cast<formula*>(f)->accept(*markvisitor_);
formula* r = down_cast<mark_visitor*>(markvisitor_)->result();
markops_[f->clone()] = r->clone();
return r;
} }
bool formula*
simplify_mark(formula*& f) mark_tools::simplify_mark(const formula* f)
{ {
simplify_mark_visitor v; if (!f->is_marked())
const_cast<formula*>(f)->accept(v); return f->clone();
f->destroy();
f = v.result(); f2f_map::iterator i = simpmark_.find(f);
return v.has_mark(); if (i != simpmark_.end())
return i->second->clone();
const_cast<formula*>(f)->accept(*simpvisitor_);
formula* r = down_cast<simplify_mark_visitor*>(simpvisitor_)->result();
simpmark_[f->clone()] = r->clone();
return r;
} }
} }
......
// Copyright (C) 2010 Laboratoire de Recherche et Développement de // Copyright (C) 2010, 2011 Laboratoire de Recherche et Développement
// l'Epita (LRDE). // de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
// //
...@@ -23,18 +23,35 @@ ...@@ -23,18 +23,35 @@
#include "ltlast/formula.hh" #include "ltlast/formula.hh"
#include "ltlast/visitor.hh" #include "ltlast/visitor.hh"
#include "misc/hash.hh"
namespace spot namespace spot
{ {
namespace ltl namespace ltl
{ {
/// \brief Mark operators UConcat and EConcat. class mark_tools
/// \ingroup ltl_rewriting {
/// public:
/// \param f The formula to rewrite. /// \brief Mark operators UConcat and EConcat.
formula* mark_concat_ops(const formula* f); /// \ingroup ltl_rewriting
///
/// \param f The formula to rewrite.
formula* mark_concat_ops(const formula* f);
formula* simplify_mark(const formula* f);
mark_tools();
~mark_tools();
private:
typedef Sgi::hash_map<const formula*, const formula*,
ptr_hash<formula> > f2f_map;
f2f_map simpmark_;
f2f_map markops_;
visitor* simpvisitor_;
visitor* markvisitor_;
};
bool simplify_mark(formula*& f);
} }
} }
......
...@@ -108,6 +108,7 @@ namespace spot ...@@ -108,6 +108,7 @@ namespace spot
bdd_dict* dict; bdd_dict* dict;
ltl_simplifier* ls; ltl_simplifier* ls;
mark_tools mt;
typedef bdd_dict::fv_map fv_map; typedef bdd_dict::fv_map fv_map;
typedef bdd_dict::vf_map vf_map; typedef bdd_dict::vf_map vf_map;
...@@ -1760,7 +1761,11 @@ namespace spot ...@@ -1760,7 +1761,11 @@ namespace spot
// Handle a Miyano-Hayashi style unrolling for // Handle a Miyano-Hayashi style unrolling for
// rational operators. Marked nodes correspond to // rational operators. Marked nodes correspond to
// subformulae in the Miyano-Hayashi set. // subformulae in the Miyano-Hayashi set.
if (simplify_mark(dest)) formula* tmp = d_.mt.simplify_mark(dest);
dest->destroy();
dest = tmp;
if (dest->is_marked())
{ {
// Make the promise that we will exit marked sets. // Make the promise that we will exit marked sets.
int a = int a =
...@@ -1772,7 +1777,7 @@ namespace spot ...@@ -1772,7 +1777,7 @@ namespace spot
// We have no marked operators, but still // We have no marked operators, but still
// have other rational operator to check. // have other rational operator to check.
// Start a new marked cycle. // Start a new marked cycle.
formula* dest2 = mark_concat_ops(dest); formula* dest2 = d_.mt.mark_concat_ops(dest);
dest->destroy(); dest->destroy();
dest = dest2; dest = dest2;
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment