Introduce rational operators and trivial simplification rules.
Trivial simplifications rules (such as "FFa=Fa" or "x&1=x") are performed any time a formule is instanciated. * src/ltlast/constant.hh, src/ltlast/constant.cc (true_instance, true_instance_): Declare the true_instance_ as a static member, and move true_instance() into the .hh so it gets inlined. Have true_instance_ as a class variable will ensure that it is the first formula instantiated. Binop simplifications rely on this to order arguments. (false_instance, false_instance_): Likewise. (empty_word_instance, empty_word_instance_): New method and static member. * src/ltlast/formula.hh (formula::formula): If max_count_ ever loops, skip the first three values so that constants always have smaller hash codes. * src/ltlast/binop.hh, src/ltlast/binop.cc (instance): Add simplifications and document them. * src/ltlast/multop.hh (multop::Concat): New operator. * src/ltlast/multop.cc (op_name): Handle Concat. (instance): Inline Concat arguments without reordering. Handle absorbent and neutral elements for all operators. * src/ltlast/unop.hh (unop::Star): New operator. * src/ltlast/unop.cc (op_name): Handle Star. (instance): Handle Star, and add trivial simplifications for other unary operators. * src/ltlparse/ltlparse.yy (OP_CONCAT, OP_STAR, CONST_EMPTYWORD): Declare these new operators and add rules for them. * src/ltlparse/ltlscan.ll (OP_CONCAT, OP_STAR, CONST_EMPTYWORD): Output these new operators. * src/ltltest/equals.test: New tests. * src/ltltest/parse.test: Remove redundant test. * src/ltltest/tunabbrev.test, src/tgbatest/emptchk.test: Adjust tests. * src/ltlvisit/basicreduce.cc, src/ltlvisit/contain.cc, src/ltlvisit/nenoform.cc, src/ltlvisit/reduce.cc, src/ltlvisit/syntimpl.cc, src/ltlvisit/tostring.cc, src/ltlvisit/tunabbrev.cc: Complete visitors to handle new operators. * src/ltltest/nenoform.test: More tests. * src/ltlvisit/lunabbrev.cc (unabbreviate_logic_visitor::visit): Clone formulae before instance() function actually have a chance to destroy them. * src/tgba/formula2bdd.cc, src/tgbaalgos/eltl2tgba_lacim.cc, src/tgbaalgos/ltl2taa.cc, src/tgbaalgos/ltl2tgba_fm.cc, src/tgbaalgos/ltl2tgba_lacim.cc: Adjust switches to assert on new operators.
This commit is contained in:
parent
4fcc4f829c
commit
546559b8c3
29 changed files with 575 additions and 120 deletions
|
|
@ -24,6 +24,8 @@
|
|||
#include <cassert>
|
||||
#include <utility>
|
||||
#include "binop.hh"
|
||||
#include "unop.hh"
|
||||
#include "constant.hh"
|
||||
#include "visitor.hh"
|
||||
#include <iostream>
|
||||
|
||||
|
|
@ -127,25 +129,127 @@ namespace spot
|
|||
|
||||
binop::map binop::instances;
|
||||
|
||||
binop*
|
||||
formula*
|
||||
binop::instance(type op, formula* first, formula* second)
|
||||
{
|
||||
// Sort the operands of commutative operators, so that for
|
||||
// example the formula instance for 'a xor b' is the same as
|
||||
// that for 'b xor a'.
|
||||
|
||||
/// Trivial identities:
|
||||
switch (op)
|
||||
{
|
||||
case Xor:
|
||||
{
|
||||
// Xor is commutative: sort operands.
|
||||
formula_ptr_less_than cmp;
|
||||
if (cmp(second, first) > 0)
|
||||
std::swap(first, second);
|
||||
}
|
||||
// - (1 ^ Exp) = !Exp
|
||||
// - (0 ^ Exp) = Exp
|
||||
if (first == constant::true_instance())
|
||||
return unop::instance(unop::Not, second);
|
||||
if (first == constant::false_instance())
|
||||
return second;
|
||||
// We expect constants to appear first, because they are
|
||||
// instantiated first.
|
||||
assert(second != constant::false_instance());
|
||||
assert(second != constant::true_instance());
|
||||
break;
|
||||
case Equiv:
|
||||
if (second < first)
|
||||
std::swap(first, second);
|
||||
{
|
||||
// Equiv is commutative: sort operands.
|
||||
formula_ptr_less_than cmp;
|
||||
if (cmp(second, first) > 0)
|
||||
std::swap(first, second);
|
||||
}
|
||||
// - (0 <=> Exp) = !Exp
|
||||
// - (1 <=> Exp) = Exp
|
||||
if (first == constant::false_instance())
|
||||
return unop::instance(unop::Not, second);
|
||||
if (first == constant::true_instance())
|
||||
return second;
|
||||
// We expect constants to appear first, because they are
|
||||
// instantiated first.
|
||||
assert(second != constant::false_instance());
|
||||
assert(second != constant::true_instance());
|
||||
break;
|
||||
case Implies:
|
||||
/// - (1 => Exp) = Exp
|
||||
/// - (0 => Exp) = 0
|
||||
/// - (Exp => 1) = 1
|
||||
/// - (Exp => 0) = !Exp
|
||||
if (first == constant::true_instance())
|
||||
return second;
|
||||
if (first == constant::false_instance())
|
||||
{
|
||||
second->destroy();
|
||||
return first;
|
||||
}
|
||||
if (second == constant::true_instance())
|
||||
{
|
||||
first->destroy();
|
||||
return second;
|
||||
}
|
||||
if (second == constant::false_instance())
|
||||
return unop::instance(unop::Not, first);
|
||||
break;
|
||||
case U:
|
||||
case R:
|
||||
/// - (Exp U 1) = 1
|
||||
/// - (Exp U 0) = 0
|
||||
/// - (0 U Exp) = Exp
|
||||
if (second == constant::true_instance()
|
||||
|| second == constant::false_instance()
|
||||
|| first == constant::false_instance())
|
||||
{
|
||||
first->destroy();
|
||||
return second;
|
||||
}
|
||||
break;
|
||||
case W:
|
||||
/// - (Exp W 1) = 1
|
||||
/// - (0 W Exp) = Exp
|
||||
/// - (1 W Exp) = 1
|
||||
if (second == constant::true_instance()
|
||||
|| first == constant::false_instance())
|
||||
{
|
||||
first->destroy();
|
||||
return second;
|
||||
}
|
||||
if (first == constant::true_instance())
|
||||
{
|
||||
second->destroy();
|
||||
return first;
|
||||
}
|
||||
break;
|
||||
case R:
|
||||
/// - (Exp R 1) = 1
|
||||
/// - (Exp R 0) = 0
|
||||
/// - (1 R Exp) = Exp
|
||||
if (second == constant::true_instance()
|
||||
|| second == constant::false_instance()
|
||||
|| first == constant::true_instance())
|
||||
{
|
||||
first->destroy();
|
||||
return second;
|
||||
}
|
||||
break;
|
||||
case M:
|
||||
// Non commutative operators.
|
||||
/// - (Exp M 0) = 0
|
||||
/// - (1 M Exp) = Exp
|
||||
/// - (0 M Exp) = 0
|
||||
if (second == constant::false_instance()
|
||||
|| first == constant::true_instance())
|
||||
{
|
||||
first->destroy();
|
||||
return second;
|
||||
}
|
||||
if (first == constant::false_instance())
|
||||
{
|
||||
second->destroy();
|
||||
return first;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,9 +56,37 @@ namespace spot
|
|||
M //< strong release (dual of weak until)
|
||||
};
|
||||
|
||||
/// Build an unary operator with operation \a op and
|
||||
/// \brief Build a unary operator with operation \a op and
|
||||
/// children \a first and \a second.
|
||||
static binop* instance(type op, formula* first, formula* second);
|
||||
///
|
||||
/// Some reordering will be performed on arguments of commutative
|
||||
/// operators (Xor and Equiv) to ensure that for instance (a <=> b)
|
||||
/// is the same formula as (b <=> a).
|
||||
///
|
||||
/// Furthermore, the following trivial simplifications are
|
||||
/// performed (the left formula is rewritten as the right
|
||||
/// formula):
|
||||
/// - (1 => Exp) = Exp
|
||||
/// - (0 => Exp) = 0
|
||||
/// - (Exp => 1) = 1
|
||||
/// - (Exp => 0) = !Exp
|
||||
/// - (1 ^ Exp) = !Exp
|
||||
/// - (0 ^ Exp) = Exp
|
||||
/// - (0 <=> Exp) = !Exp
|
||||
/// - (1 <=> Exp) = Exp
|
||||
/// - (Exp U 1) = 1
|
||||
/// - (Exp U 0) = 0
|
||||
/// - (0 U Exp) = Exp
|
||||
/// - (Exp W 1) = 1
|
||||
/// - (0 W Exp) = Exp
|
||||
/// - (1 W Exp) = 1
|
||||
/// - (Exp R 1) = 1
|
||||
/// - (Exp R 0) = 0
|
||||
/// - (1 R Exp) = Exp
|
||||
/// - (Exp M 0) = 0
|
||||
/// - (1 M Exp) = Exp
|
||||
/// - (0 M Exp) = 0
|
||||
static formula* instance(type op, formula* first, formula* second);
|
||||
|
||||
virtual void accept(visitor& v);
|
||||
virtual void accept(const_visitor& v) const;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (C) 2009 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2009, 2010 Laboratoire de Recherche et D<>veloppement
|
||||
// de l'Epita (LRDE).
|
||||
// Copyright (C) 2003, 2005 Laboratoire d'Informatique de Paris
|
||||
// 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
|
||||
// Université Pierre et Marie Curie.
|
||||
// 6 (LIP6), d<EFBFBD>partement Syst<73>mes R<>partis Coop<6F>ratifs (SRC),
|
||||
// Universit<EFBFBD> Pierre et Marie Curie.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -29,6 +29,10 @@ namespace spot
|
|||
{
|
||||
namespace ltl
|
||||
{
|
||||
constant constant::true_instance_(constant::True);
|
||||
constant constant::false_instance_(constant::False);
|
||||
constant constant::empty_word_instance_(constant::EmptyWord);
|
||||
|
||||
constant::constant(type val)
|
||||
: val_(val)
|
||||
{
|
||||
|
|
@ -47,6 +51,8 @@ namespace spot
|
|||
return "constant(1)";
|
||||
case False:
|
||||
return "constant(0)";
|
||||
case EmptyWord:
|
||||
return "constant(e)";
|
||||
}
|
||||
// Unreachable code.
|
||||
assert(0);
|
||||
|
|
@ -80,24 +86,12 @@ namespace spot
|
|||
return "1";
|
||||
case False:
|
||||
return "0";
|
||||
case EmptyWord:
|
||||
return "#e";
|
||||
}
|
||||
// Unreachable code.
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
constant*
|
||||
constant::false_instance()
|
||||
{
|
||||
static constant f(constant::False);
|
||||
return &f;
|
||||
}
|
||||
|
||||
constant*
|
||||
constant::true_instance()
|
||||
{
|
||||
static constant t(constant::True);
|
||||
return &t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (C) 2009 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2009, 2010 Laboratoire de Recherche et D<>veloppement
|
||||
// de l'Epita (LRDE).
|
||||
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -38,7 +36,7 @@ namespace spot
|
|||
class constant : public formula
|
||||
{
|
||||
public:
|
||||
enum type { False, True };
|
||||
enum type { False, True, EmptyWord };
|
||||
virtual void accept(visitor& v);
|
||||
virtual void accept(const_visitor& v) const;
|
||||
|
||||
|
|
@ -50,9 +48,11 @@ namespace spot
|
|||
virtual std::string dump() const;
|
||||
|
||||
/// Get the sole instance of spot::ltl::constant::constant(True).
|
||||
static constant* true_instance();
|
||||
static constant* true_instance() { return &true_instance_; }
|
||||
/// Get the sole instance of spot::ltl::constant::constant(False).
|
||||
static constant* false_instance();
|
||||
static constant* false_instance() { return &false_instance_; }
|
||||
/// Get the sole instance of spot::ltl::constant::constant(EmptyWord).
|
||||
static constant* empty_word_instance() { return &empty_word_instance_; }
|
||||
|
||||
protected:
|
||||
constant(type val);
|
||||
|
|
@ -60,6 +60,12 @@ namespace spot
|
|||
|
||||
private:
|
||||
type val_;
|
||||
|
||||
static constant true_instance_;
|
||||
static constant false_instance_;
|
||||
static constant empty_word_instance_;
|
||||
// If you add new constants here, be sure to update the
|
||||
// formula::formula() constructor.
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (C) 2008, 2009 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2008, 2009, 2010 Laboratoire de Recherche et D<>veloppement
|
||||
// de l'Epita (LRDE).
|
||||
// Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de
|
||||
// Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
|
||||
// Université Pierre et Marie Curie.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -73,7 +71,15 @@ namespace spot
|
|||
class formula
|
||||
{
|
||||
public:
|
||||
formula() : count_(++max_count) {}
|
||||
formula() : count_(max_count++)
|
||||
{
|
||||
// If the counter of formulae ever loops, we want to skip the
|
||||
// first three values, because they are permanently associated
|
||||
// to constants, and its convenient to have constants smaller
|
||||
// than all other formulae.
|
||||
if (max_count == 0)
|
||||
max_count = 3;
|
||||
}
|
||||
|
||||
/// Entry point for vspot::ltl::visitor instances.
|
||||
virtual void accept(visitor& v) = 0;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (C) 2009 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2009, 2010 Laboratoire de Recherche et D<>veloppement
|
||||
// de l'Epita (LRDE).
|
||||
// Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de
|
||||
// Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
|
||||
// Université Pierre et Marie Curie.
|
||||
// Paris 6 (LIP6), d<EFBFBD>partement Syst<73>mes R<>partis Coop<6F>ratifs (SRC),
|
||||
// Universit<EFBFBD> Pierre et Marie Curie.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -110,6 +110,8 @@ namespace spot
|
|||
return "And";
|
||||
case Or:
|
||||
return "Or";
|
||||
case Concat:
|
||||
return "Concat";
|
||||
}
|
||||
// Unreachable code.
|
||||
assert(0);
|
||||
|
|
@ -146,13 +148,24 @@ namespace spot
|
|||
}
|
||||
else
|
||||
{
|
||||
// All operator except "Concat" not commutative, so
|
||||
// we just keep a list of the inlined arguments that
|
||||
// should later be added to the vector.
|
||||
// For concat we have to keep track of the order of
|
||||
// all the arguments.
|
||||
if (op == Concat)
|
||||
inlined.push_back(*i);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
v->insert(v->end(), inlined.begin(), inlined.end());
|
||||
if (op == Concat)
|
||||
*v = inlined;
|
||||
else
|
||||
v->insert(v->end(), inlined.begin(), inlined.end());
|
||||
}
|
||||
|
||||
std::sort(v->begin(), v->end(), formula_ptr_less_than());
|
||||
if (op != Concat)
|
||||
std::sort(v->begin(), v->end(), formula_ptr_less_than());
|
||||
|
||||
formula* neutral;
|
||||
formula* abs;
|
||||
|
|
@ -166,15 +179,19 @@ namespace spot
|
|||
neutral = constant::false_instance();
|
||||
abs = constant::true_instance();
|
||||
break;
|
||||
case Concat:
|
||||
neutral = constant::empty_word_instance();
|
||||
abs = constant::false_instance();
|
||||
break;
|
||||
default:
|
||||
neutral = 0;
|
||||
abs = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove duplicates. We can't use std::unique(), because we
|
||||
// must destroy() any formula we drop. Also ignore neutral
|
||||
// elements and handle absorbent elements.
|
||||
// Remove duplicates (except for Concat). We can't use
|
||||
// std::unique(), because we must destroy() any formula we drop.
|
||||
// Also ignore neutral elements and handle absorbent elements.
|
||||
{
|
||||
formula* last = 0;
|
||||
vec::iterator i = v->begin();
|
||||
|
|
@ -194,7 +211,9 @@ namespace spot
|
|||
}
|
||||
else
|
||||
{
|
||||
last = *i++;
|
||||
if (op != Concat) // Don't remove duplicates for Concat.
|
||||
last = *i;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (C) 2009 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2009, 2010 Laboratoire de Recherche et D<>veloppement
|
||||
// de l'Epita (LRDE).
|
||||
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris
|
||||
// 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
|
||||
// Université Pierre et Marie Curie.
|
||||
// 6 (LIP6), d<EFBFBD>partement Syst<73>mes R<>partis Coop<6F>ratifs (SRC),
|
||||
// Universit<EFBFBD> Pierre et Marie Curie.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -38,12 +38,10 @@ namespace spot
|
|||
|
||||
/// \brief Multi-operand operators.
|
||||
/// \ingroup ltl_ast
|
||||
///
|
||||
/// These operators are considered commutative and associative.
|
||||
class multop : public ref_formula
|
||||
{
|
||||
public:
|
||||
enum type { Or, And };
|
||||
enum type { Or, And, Concat };
|
||||
|
||||
/// List of formulae.
|
||||
typedef std::vector<formula*> vec;
|
||||
|
|
@ -51,29 +49,46 @@ namespace spot
|
|||
/// \brief Build a spot::ltl::multop with two children.
|
||||
///
|
||||
/// If one of the children itself is a spot::ltl::multop
|
||||
/// with the same type, it will be merged. I.e., children
|
||||
/// if that child will be added, and that child itself will
|
||||
/// with the same type, it will be inlined. I.e., children
|
||||
/// of that child will be added, and that child itself will
|
||||
/// be destroyed. This allows incremental building of
|
||||
/// n-ary ltl::multop.
|
||||
///
|
||||
/// This functions can perform slight optimizations and
|
||||
/// may not return an ltl::multop objects. For instance
|
||||
/// if \c first and \c second are equal, that formula is
|
||||
/// returned as-is.
|
||||
/// may not return an ltl::multop object. See the other
|
||||
/// instance function for the list of rewritings.
|
||||
static formula* instance(type op, formula* first, formula* second);
|
||||
|
||||
/// \brief Build a spot::ltl::multop with many children.
|
||||
///
|
||||
/// Same as the other instance() function, but take a vector of
|
||||
/// formula in argument. This vector is acquired by the
|
||||
/// formulae as argument. This vector is acquired by the
|
||||
/// spot::ltl::multop class, the caller should allocate it with
|
||||
/// \c new, but not use it (especially not destroy it) after it
|
||||
/// has been passed to spot::ltl::multop.
|
||||
///
|
||||
/// This functions can perform slight optimizations and
|
||||
/// may not return an ltl::multop objects. For instance
|
||||
/// if the vector contain only one unique element, this
|
||||
/// this formula will be returned as-is.
|
||||
/// All operators (Or, And, Concat) are associative, and are
|
||||
/// automatically inlined. Or and And are commutative, so their
|
||||
/// argument are also sorted, to ensure that "a & b" is equal to
|
||||
/// "b & a". For Or and And, duplicate arguments are also
|
||||
/// removed.
|
||||
///
|
||||
/// Furthermore this function can perform slight optimizations
|
||||
/// and may not return an ltl::multop object. For instance if
|
||||
/// the vector contains only one unique element, this this
|
||||
/// formula will be returned as-is. Neutral and absorbent element
|
||||
/// are also taken care of. The following rewriting are performed
|
||||
/// (the left patterns are rewritten as shown on the right):
|
||||
///
|
||||
/// - Concat(Exps1...,#e,Exps2...) = Concat(Exps1...,Exps2...)
|
||||
/// - Concat(Exps1...,0,Exps2...) = 0
|
||||
/// - Concat(Exp) = Exp
|
||||
/// - And(Exps1...,1,Exps2...) = And(Exps1...,Exps2...)
|
||||
/// - And(Exps1...,0,Exps2...) = 0
|
||||
/// - And(Exp) = Exp
|
||||
/// - Or(Exps1...,1,Exps2...) = 1
|
||||
/// - Or(Exps1...,0,Exps2...) = And(Exps1...,Exps2...)
|
||||
/// - Or(Exp) = Exp
|
||||
static formula* instance(type op, vec* v);
|
||||
|
||||
virtual void accept(visitor& v);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (C) 2009 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2009, 2010 Laboratoire de Recherche et D<>veloppement
|
||||
// de l'Epita (LRDE).
|
||||
// Copyright (C) 2003, 2005 Laboratoire d'Informatique de Paris
|
||||
// 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
|
||||
// Université Pierre et Marie Curie.
|
||||
// 6 (LIP6), d<EFBFBD>partement Syst<73>mes R<>partis Coop<6F>ratifs (SRC),
|
||||
// Universit<EFBFBD> Pierre et Marie Curie.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
#include "visitor.hh"
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "constant.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
|
@ -98,6 +99,8 @@ namespace spot
|
|||
return "G";
|
||||
case Finish:
|
||||
return "Finish";
|
||||
case Star:
|
||||
return "Star";
|
||||
}
|
||||
// Unreachable code.
|
||||
assert(0);
|
||||
|
|
@ -106,9 +109,78 @@ namespace spot
|
|||
|
||||
unop::map unop::instances;
|
||||
|
||||
unop*
|
||||
formula*
|
||||
unop::instance(type op, formula* child)
|
||||
{
|
||||
|
||||
// Some trivial simplifications.
|
||||
switch (op)
|
||||
{
|
||||
// We have (0*) == (#e)
|
||||
// (#e*) == (#e)
|
||||
case Star:
|
||||
if (child == constant::false_instance()
|
||||
|| child == constant::empty_word_instance())
|
||||
return constant::empty_word_instance();
|
||||
|
||||
// -- fall thru --
|
||||
|
||||
case F:
|
||||
case G:
|
||||
{
|
||||
// F, G, * are idempotent.
|
||||
unop* u = dynamic_cast<unop*>(child);
|
||||
if (u && u->op() == op)
|
||||
return u;
|
||||
|
||||
if (op == Star)
|
||||
break;
|
||||
|
||||
// F(0) = G(0) = 0
|
||||
// F(1) = G(1) = 1
|
||||
if (child == constant::false_instance()
|
||||
|| child == constant::true_instance())
|
||||
return child;
|
||||
// F(#e) = G(#e) = 1
|
||||
if (child == constant::empty_word_instance())
|
||||
return constant::true_instance();
|
||||
}
|
||||
|
||||
|
||||
case Not:
|
||||
{
|
||||
// !1 = 0
|
||||
if (child == constant::true_instance())
|
||||
return constant::false_instance();
|
||||
// !0 = 1
|
||||
if (child == constant::false_instance())
|
||||
return constant::true_instance();
|
||||
// Not is an involution.
|
||||
unop* u = dynamic_cast<unop*>(child);
|
||||
if (u && u->op() == op)
|
||||
{
|
||||
formula* c = u->child()->clone();
|
||||
u->destroy();
|
||||
return c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case X:
|
||||
// X(1) = 1, X(0) = 0
|
||||
if (child == constant::true_instance()
|
||||
|| child == constant::false_instance())
|
||||
return child;
|
||||
// X(#e) = 1
|
||||
if (child == constant::empty_word_instance())
|
||||
return constant::true_instance();
|
||||
break;
|
||||
|
||||
case Finish:
|
||||
// No simplifications for Finish.
|
||||
break;
|
||||
}
|
||||
|
||||
pair p(op, child);
|
||||
map::iterator i = instances.find(p);
|
||||
if (i != instances.end())
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (C) 2009 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2009, 2010 Laboratoire de Recherche et D<>veloppement
|
||||
// de l'Epita (LRDE).
|
||||
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris
|
||||
// 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
|
||||
// Université Pierre et Marie Curie.
|
||||
// 6 (LIP6), d<EFBFBD>partement Syst<73>mes R<>partis Coop<6F>ratifs (SRC),
|
||||
// Universit<EFBFBD> Pierre et Marie Curie.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -40,11 +40,40 @@ namespace spot
|
|||
class unop : public ref_formula
|
||||
{
|
||||
public:
|
||||
enum type { Not, X, F, G, Finish }; // Finish is used in ELTL formulae.
|
||||
enum type {
|
||||
// LTL
|
||||
Not, X, F, G,
|
||||
// ELTL
|
||||
Finish,
|
||||
// Kleene Star
|
||||
Star,
|
||||
};
|
||||
|
||||
/// Build an unary operator with operation \a op and
|
||||
/// \brief Build an unary operator with operation \a op and
|
||||
/// child \a child.
|
||||
static unop* instance(type op, formula* child);
|
||||
///
|
||||
/// The following trivial simplifications are performed
|
||||
/// automatically (the left expression is rewritten as the right
|
||||
/// expression):
|
||||
/// - 0* = #e
|
||||
/// - #e* = #e
|
||||
/// - Exp** = Exp*
|
||||
/// - FF(Exp) = F(Exp)
|
||||
/// - GG(Exp) = G(Exp)
|
||||
/// - F(0) = 0
|
||||
/// - G(0) = 0
|
||||
/// - F(1) = 1
|
||||
/// - G(1) = 1
|
||||
/// - F(#e) = 1
|
||||
/// - G(#e) = 1
|
||||
/// - !1 = 0
|
||||
/// - !0 = 1
|
||||
/// - !!Exp = Exp
|
||||
///
|
||||
/// This rewriting implies that it is not possible to build an
|
||||
/// LTL formula object that is SYNTACTICALLY equal to one of
|
||||
/// these left expressions.
|
||||
static formula* instance(type op, formula* child);
|
||||
|
||||
virtual void accept(visitor& v);
|
||||
virtual void accept(const_visitor& v) const;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue