spot  1.99.3
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
formula.hh
Go to the documentation of this file.
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
3 // Laboratoire de Recherche et Développement de l'Epita (LRDE).
4 // Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de
5 //
6 // This file is part of Spot, a model checking library.
7 //
8 // Spot is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
12 //
13 // Spot is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 // License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
23 #pragma once
24 
25 #include "misc/common.hh"
26 #include <string>
27 #include <cassert>
28 #include "predecl.hh"
29 #include <list>
30 
31 namespace spot
32 {
33  namespace ltl
34  {
38 
41 
44 
48 
51 
54 
57 
60 
63 
64 
71  class SPOT_API formula
72  {
73  public:
75  enum opkind { Constant,
76  AtomicProp,
77  UnOp,
78  BinOp,
79  MultOp,
80  BUnOp };
81 
82  protected:
83  formula(opkind k) : serial_(max_serial++), kind_(k)
84  {
85  // If the counter of formulae ever loops, we want to skip the
86  // first three values, because they are permanently associated
87  // to constants, and it is convenient to have constants smaller
88  // than all other formulae.
89  if (max_serial == 0)
90  max_serial = 3;
91  }
92 
93  public:
95  virtual void accept(visitor& v) const = 0;
96 
100  const formula* clone() const
101  {
102  ++refs_;
103  return this;
104  }
105 
107  void destroy() const
108  {
109  // Delete if this is the last node, and it is not a constant.
110  if (!refs_)
111  {
112  if (kind() != Constant)
113  delete this;
114  }
115  else
116  {
117  --refs_;
118  }
119  }
120 
122  virtual std::string dump() const = 0;
123 
125  opkind kind() const
126  {
127  return kind_;
128  }
129 
131  // Properties //
133 
135  bool is_boolean() const
136  {
137  return is.boolean;
138  }
139 
142  {
143  return is.sugar_free_boolean;
144  }
145 
150  bool is_in_nenoform() const
151  {
152  return is.in_nenoform;
153  }
154 
157  {
158  return is.syntactic_si;
159  }
160 
162  bool is_sugar_free_ltl() const
163  {
164  return is.sugar_free_ltl;
165  }
166 
168  bool is_ltl_formula() const
169  {
170  return is.ltl_formula;
171  }
172 
174  bool is_psl_formula() const
175  {
176  return is.psl_formula;
177  }
178 
180  bool is_sere_formula() const
181  {
182  return is.sere_formula;
183  }
184 
187  bool is_finite() const
188  {
189  return is.finite;
190  }
191 
195 
209  bool is_eventual() const
213  {
214  return is.eventual;
215  }
216 
220 
234  bool is_universal() const
238  {
239  return is.universal;
240  }
241 
243  bool is_syntactic_safety() const
244  {
245  return is.syntactic_safety;
246  }
247 
250  {
251  return is.syntactic_guarantee;
252  }
253 
256  {
257  return is.syntactic_obligation;
258  }
259 
262  {
263  return is.syntactic_recurrence;
264  }
265 
268  {
269  return is.syntactic_persistence;
270  }
271 
273  bool is_marked() const
274  {
275  return !is.not_marked;
276  }
277 
279  bool accepts_eword() const
280  {
281  return is.accepting_eword;
282  }
283 
284  bool has_lbt_atomic_props() const
285  {
286  return is.lbt_atomic_props;
287  }
288 
289  bool has_spin_atomic_props() const
290  {
291  return is.spin_atomic_props;
292  }
293 
295  unsigned get_props() const
296  {
297  return props;
298  }
299 
301  size_t
302  hash() const
303  {
304  return serial_;
305  }
306  protected:
307  virtual ~formula()
308  {
309  }
310 
312  size_t serial_;
313 
314  // The number of actual references is refs_ + 1.
315  mutable unsigned refs_ = 0;
317  static size_t max_serial;
318  opkind kind_;
319 
320  struct ltl_prop
321  {
322  // All properties here should be expressed in such a a way
323  // that property(f && g) is just property(f)&property(g).
324  // This allows us to compute all properties of a compound
325  // formula in one operation.
326  //
327  // For instance we do not use a property that says "has
328  // temporal operator", because it would require an OR between
329  // the two arguments. Instead we have a property that
330  // says "no temporal operator", and that one is computed
331  // with an AND between the arguments.
332  //
333  // Also choose a name that makes sense when prefixed with
334  // "the formula is".
335  bool boolean:1; // No temporal operators.
336  bool sugar_free_boolean:1; // Only AND, OR, and NOT operators.
337  bool in_nenoform:1; // Negative Normal Form.
338  bool syntactic_si:1; // LTL-X or siPSL
339  bool sugar_free_ltl:1; // No F and G operators.
340  bool ltl_formula:1; // Only LTL operators.
341  bool psl_formula:1; // Only PSL operators.
342  bool sere_formula:1; // Only SERE operators.
343  bool finite:1; // Finite SERE formulae, or Bool+X forms.
344  bool eventual:1; // Purely eventual formula.
345  bool universal:1; // Purely universal formula.
346  bool syntactic_safety:1; // Syntactic Safety Property.
347  bool syntactic_guarantee:1; // Syntactic Guarantee Property.
348  bool syntactic_obligation:1; // Syntactic Obligation Property.
349  bool syntactic_recurrence:1; // Syntactic Recurrence Property.
350  bool syntactic_persistence:1; // Syntactic Persistence Property.
351  bool not_marked:1; // No occurrence of EConcatMarked.
352  bool accepting_eword:1; // Accepts the empty word.
353  bool lbt_atomic_props:1; // Use only atomic propositions like p42.
354  bool spin_atomic_props:1; // Use only spin-compatible atomic props.
355  };
356  union
357  {
358  // Use an unsigned for fast computation of all properties.
359  unsigned props;
360  ltl_prop is;
361  };
362  };
363 
364 
369  SPOT_API
370  const formula* get_literal(const formula* f);
371 
373  inline
374  bool
375  is_literal(const formula* f)
376  {
377  return (f->kind() == formula::AtomicProp
378  // The only unary operator that is Boolean is Not,
379  // and if f is in nenoform, Not can only occur in
380  // front of an atomic proposition. So with this
381  // check we do not have to cast f to check what
382  // operator it is and the type of its child.
383  || (f->is_boolean() && f->is_in_nenoform()
384  && f->kind() == formula::UnOp));
385  }
386 
387 
389  SPOT_API
390  int atomic_prop_cmp(const formula* f, const formula* g);
391 
392 
407  public std::binary_function<const formula*, const formula*, bool>
408  {
409  bool
410  operator()(const formula* left, const formula* right) const
411  {
412  assert(left);
413  assert(right);
414  if (left == right)
415  return false;
416 
417  size_t l = left->hash();
418  size_t r = right->hash();
419  if (l != r)
420  return l < r;
421  // Because the hash code assigned to each formula is the
422  // number of formulae constructed so far, it is very unlikely
423  // that we will ever reach a case were two different formulae
424  // have the same hash. This will happen only ever with have
425  // produced 256**sizeof(size_t) formulae (i.e. max_count has
426  // looped back to 0 and started over). In that case we can
427  // order two formulae by looking at their text representation.
428  // We could be more efficient and look at their AST, but it's
429  // not worth the burden. (Also ordering pointers is ruled out
430  // because it breaks the determinism of the implementation.)
431  return left->dump() < right->dump();
432  }
433  };
434 
445  public std::binary_function<const formula*, const formula*, bool>
446  {
447  bool
448  operator()(const formula* left, const formula* right) const
449  {
450  assert(left);
451  assert(right);
452  if (left == right)
453  return false;
454 
455  // We want Boolean formulae first.
456  bool lib = left->is_boolean();
457  if (lib != right->is_boolean())
458  return lib;
459 
460  // We have two Boolean formulae
461  if (lib)
462  {
463  bool lconst = left->kind() == formula::Constant;
464  bool rconst = right->kind() == formula::Constant;
465  if (lconst != rconst)
466  return lconst;
467  if (!lconst)
468  {
469  // Literals should come first
470  const formula* litl = get_literal(left);
471  const formula* litr = get_literal(right);
472  if (!litl != !litr)
473  return litl;
474  if (litl)
475  {
476  // And they should be sorted alphabetically
477  int cmp = atomic_prop_cmp(litl, litr);
478  if (cmp)
479  return cmp < 0;
480  }
481  }
482  }
483 
484  size_t l = left->hash();
485  size_t r = right->hash();
486  if (l != r)
487  return l < r;
488  // Because the hash code assigned to each formula is the
489  // number of formulae constructed so far, it is very unlikely
490  // that we will ever reach a case were two different formulae
491  // have the same hash. This will happen only ever with have
492  // produced 256**sizeof(size_t) formulae (i.e. max_count has
493  // looped back to 0 and started over). In that case we can
494  // order two formulae by looking at their text representation.
495  // We could be more efficient and look at their AST, but it's
496  // not worth the burden. (Also ordering pointers is ruled out
497  // because it breaks the determinism of the implementation.)
498  return left->dump() < right->dump();
499  }
500  };
501 
503  SPOT_API
504  std::ostream& print_formula_props(std::ostream& out,
505  const formula* f,
506  bool abbreviated = false);
507 
509  SPOT_API
510  std::list<std::string> list_formula_props(const formula* f);
511  }
512 }
513 
514 #ifndef SWIG
515 namespace std
516 {
517  template <>
518  struct hash<const spot::ltl::formula*>
519  {
520  size_t operator()(const spot::ltl::formula* x) const noexcept
521  {
522  assert(x);
523  return x->hash();
524  }
525  };
526 }
527 #endif
Definition: public.hh:31
size_t hash() const
Return a hash key for the formula.
Definition: formula.hh:302
bool is_sugar_free_ltl() const
Whether the formula avoids the F and G operators.
Definition: formula.hh:162
void destroy() const
Release this node.
Definition: formula.hh:107
virtual std::string dump() const =0
Return a canonic representation of the formula.
bool is_in_nenoform() const
Whether the formula is in negative normal form.
Definition: formula.hh:150
bool is_syntactic_recurrence() const
Whether a PSL/LTL formula is syntactic recurrence property.
Definition: formula.hh:261
bool is_marked() const
Whether the formula has an occurrence of EConcatMarked.
Definition: formula.hh:273
bool is_syntactic_stutter_invariant() const
Whether the formula is syntactically stutter_invariant.
Definition: formula.hh:156
Definition: formula.hh:515
bool is_syntactic_obligation() const
Whether a PSL/LTL formula is syntactic obligation property.
Definition: formula.hh:255
bool is_sugar_free_boolean() const
Whether the formula use only AND, OR, and NOT operators.
Definition: formula.hh:141
bool is_psl_formula() const
Whether the formula uses only PSL operators.
Definition: formula.hh:174
bool is_finite() const
Definition: formula.hh:187
bool is_sere_formula() const
Whether the formula uses only SERE operators.
Definition: formula.hh:180
size_t serial_
The hash key of this formula.
Definition: formula.hh:312
Strict Weak Ordering for const formula*.
Definition: formula.hh:406
const formula * clone() const
clone this node
Definition: formula.hh:100
unsigned get_props() const
The properties as a field of bits. For internal use.
Definition: formula.hh:295
Definition: formula.hh:320
Predeclare all LTL node types.
opkind
Kind of a sub-formula.
Definition: formula.hh:75
bool is_syntactic_guarantee() const
Whether a PSL/LTL formula is syntactic guarantee property.
Definition: formula.hh:249
bool accepts_eword() const
Whether the formula accepts [*0].
Definition: formula.hh:279
SPOT_API std::ostream & dump(std::ostream &os, const formula *f)
Dump a formula tree.
Strict Weak Ordering for const formula* inside ltl::multop.This is the comparison functor used by to ...
Definition: formula.hh:444
bool is_syntactic_safety() const
Whether a PSL/LTL formula is syntactic safety property.
Definition: formula.hh:243
bool is_boolean() const
Whether the formula use only boolean operators.
Definition: formula.hh:135
opkind kind() const
Return the kind of the top-level operator.
Definition: formula.hh:125
An LTL formula.
Definition: formula.hh:71
static size_t max_serial
Number of formulae created so far.
Definition: formula.hh:317
bool is_ltl_formula() const
Whether the formula uses only LTL operators.
Definition: formula.hh:168
bool is_syntactic_persistence() const
Whether a PSL/LTL formula is syntactic persistence property.
Definition: formula.hh:267

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Wed Aug 26 2015 08:42:37 for spot by doxygen 1.8.8