spot  1.2.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
formula.hh
Go to the documentation of this file.
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 Laboratoire de
3 // 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 #ifndef SPOT_LTLAST_FORMULA_HH
24 # define SPOT_LTLAST_FORMULA_HH
25 
26 #include "misc/common.hh"
27 #include <string>
28 #include <cassert>
29 #include "predecl.hh"
30 #include <list>
31 
32 namespace spot
33 {
34  namespace ltl
35  {
39 
42 
45 
49 
52 
55 
58 
61 
64 
65 
72  class SPOT_API formula
73  {
74  public:
76  enum opkind { Constant,
77  AtomicProp,
78  UnOp,
79  BinOp,
80  MultOp,
81  BUnOp,
82  AutomatOp };
83 
84  protected:
85  formula(opkind k) : count_(max_count++), kind_(k)
86  {
87  // If the counter of formulae ever loops, we want to skip the
88  // first three values, because they are permanently associated
89  // to constants, and it is convenient to have constants smaller
90  // than all other formulae.
91  if (max_count == 0)
92  max_count = 3;
93  }
94 
95  public:
97  virtual void accept(visitor& v) const = 0;
98 
103  const formula* clone() const;
108  void destroy() const;
109 
111  virtual std::string dump() const = 0;
112 
114  opkind kind() const
115  {
116  return kind_;
117  }
118 
120  // Properties //
122 
124  bool is_boolean() const
125  {
126  return is.boolean;
127  }
128 
131  {
132  return is.sugar_free_boolean;
133  }
134 
139  bool is_in_nenoform() const
140  {
141  return is.in_nenoform;
142  }
143 
145  bool is_X_free() const
146  {
147  return is.X_free;
148  }
149 
151  bool is_sugar_free_ltl() const
152  {
153  return is.sugar_free_ltl;
154  }
155 
157  bool is_ltl_formula() const
158  {
159  return is.ltl_formula;
160  }
161 
163  bool is_eltl_formula() const
164  {
165  return is.eltl_formula;
166  }
167 
169  bool is_psl_formula() const
170  {
171  return is.psl_formula;
172  }
173 
175  bool is_sere_formula() const
176  {
177  return is.sere_formula;
178  }
179 
182  bool is_finite() const
183  {
184  return is.finite;
185  }
186 
190 
204  bool is_eventual() const
208  {
209  return is.eventual;
210  }
211 
215 
229  bool is_universal() const
233  {
234  return is.universal;
235  }
236 
238  bool is_syntactic_safety() const
239  {
240  return is.syntactic_safety;
241  }
242 
245  {
246  return is.syntactic_guarantee;
247  }
248 
251  {
252  return is.syntactic_obligation;
253  }
254 
257  {
258  return is.syntactic_recurrence;
259  }
260 
263  {
264  return is.syntactic_persistence;
265  }
266 
268  bool is_marked() const
269  {
270  return !is.not_marked;
271  }
272 
274  bool accepts_eword() const
275  {
276  return is.accepting_eword;
277  }
278 
279  bool has_lbt_atomic_props() const
280  {
281  return is.lbt_atomic_props;
282  }
283 
285  unsigned get_props() const
286  {
287  return props;
288  }
289 
291  size_t
292  hash() const
293  {
294  return count_;
295  }
296  protected:
297  virtual ~formula();
298 
300  virtual void ref_() const;
303  virtual bool unref_() const;
304 
306  size_t count_;
307 
308  struct ltl_prop
309  {
310  // All properties here should be expressed in such a a way
311  // that property(f && g) is just property(f)&property(g).
312  // This allows us to compute all properties of a compound
313  // formula in one operation.
314  //
315  // For instance we do not use a property that says "has
316  // temporal operator", because it would require an OR between
317  // the two arguments. Instead we have a property that
318  // says "no temporal operator", and that one is computed
319  // with an AND between the arguments.
320  //
321  // Also choose a name that makes sense when prefixed with
322  // "the formula is".
323  bool boolean:1; // No temporal operators.
324  bool sugar_free_boolean:1; // Only AND, OR, and NOT operators.
325  bool in_nenoform:1; // Negative Normal Form.
326  bool X_free:1; // No X operators.
327  bool sugar_free_ltl:1; // No F and G operators.
328  bool ltl_formula:1; // Only LTL operators.
329  bool eltl_formula:1; // Only ELTL operators.
330  bool psl_formula:1; // Only PSL operators.
331  bool sere_formula:1; // Only SERE operators.
332  bool finite:1; // Finite SERE formulae, or Bool+X forms.
333  bool eventual:1; // Purely eventual formula.
334  bool universal:1; // Purely universal formula.
335  bool syntactic_safety:1; // Syntactic Safety Property.
336  bool syntactic_guarantee:1; // Syntactic Guarantee Property.
337  bool syntactic_obligation:1; // Syntactic Obligation Property.
338  bool syntactic_recurrence:1; // Syntactic Recurrence Property.
339  bool syntactic_persistence:1; // Syntactic Persistence Property.
340  bool not_marked:1; // No occurrence of EConcatMarked.
341  bool accepting_eword:1; // Accepts the empty word.
342  bool lbt_atomic_props:1; // Use only atomic propositions like p42.
343  };
344  union
345  {
346  // Use an unsigned for fast computation of all properties.
347  unsigned props;
348  ltl_prop is;
349  };
350 
351  private:
353  static size_t max_count;
354  opkind kind_;
355  };
356 
357 
362  SPOT_API
363  const formula* get_literal(const formula* f);
364 
366  inline
367  bool
368  is_literal(const formula* f)
369  {
370  return (f->kind() == formula::AtomicProp
371  // The only unary operator that is Boolean is Not,
372  // and if f is in nenoform, Not can only occur in
373  // front of an atomic proposition. So with this
374  // check we do not have to cast f to check what
375  // operator it is and the type of its child.
376  || (f->is_boolean() && f->is_in_nenoform()
377  && f->kind() == formula::UnOp));
378  }
379 
380 
382  SPOT_API
383  int atomic_prop_cmp(const formula* f, const formula* g);
384 
385 
400  public std::binary_function<const formula*, const formula*, bool>
401  {
402  bool
403  operator()(const formula* left, const formula* right) const
404  {
405  assert(left);
406  assert(right);
407  if (left == right)
408  return false;
409 
410  size_t l = left->hash();
411  size_t r = right->hash();
412  if (l != r)
413  return l < r;
414  // Because the hash code assigned to each formula is the
415  // number of formulae constructed so far, it is very unlikely
416  // that we will ever reach a case were two different formulae
417  // have the same hash. This will happen only ever with have
418  // produced 256**sizeof(size_t) formulae (i.e. max_count has
419  // looped back to 0 and started over). In that case we can
420  // order two formulae by looking at their text representation.
421  // We could be more efficient and look at their AST, but it's
422  // not worth the burden. (Also ordering pointers is ruled out
423  // because it breaks the determinism of the implementation.)
424  return left->dump() < right->dump();
425  }
426  };
427 
438  public std::binary_function<const formula*, const formula*, bool>
439  {
440  bool
441  operator()(const formula* left, const formula* right) const
442  {
443  assert(left);
444  assert(right);
445  if (left == right)
446  return false;
447 
448  // We want Boolean formulae first.
449  bool lib = left->is_boolean();
450  if (lib != right->is_boolean())
451  return lib;
452 
453  // We have two Boolean formulae
454  if (lib)
455  {
456  bool lconst = left->kind() == formula::Constant;
457  bool rconst = right->kind() == formula::Constant;
458  if (lconst != rconst)
459  return lconst;
460  if (!lconst)
461  {
462  // Literals should come first
463  const formula* litl = get_literal(left);
464  const formula* litr = get_literal(right);
465  if (!litl != !litr)
466  return litl;
467  if (litl)
468  {
469  // And they should be sorted alphabetically
470  int cmp = atomic_prop_cmp(litl, litr);
471  if (cmp)
472  return cmp < 0;
473  }
474  }
475  }
476 
477  size_t l = left->hash();
478  size_t r = right->hash();
479  if (l != r)
480  return l < r;
481  // Because the hash code assigned to each formula is the
482  // number of formulae constructed so far, it is very unlikely
483  // that we will ever reach a case were two different formulae
484  // have the same hash. This will happen only ever with have
485  // produced 256**sizeof(size_t) formulae (i.e. max_count has
486  // looped back to 0 and started over). In that case we can
487  // order two formulae by looking at their text representation.
488  // We could be more efficient and look at their AST, but it's
489  // not worth the burden. (Also ordering pointers is ruled out
490  // because it breaks the determinism of the implementation.)
491  return left->dump() < right->dump();
492  }
493  };
494 
510  public std::unary_function<const formula*, size_t>
511  {
512  size_t
513  operator()(const formula* that) const
514  {
515  assert(that);
516  return that->hash();
517  }
518  };
519 
521  SPOT_API
522  std::ostream& print_formula_props(std::ostream& out,
523  const formula* f,
524  bool abbreviated = false);
525 
527  SPOT_API
528  std::list<std::string> list_formula_props(const formula* f);
529  }
530 }
531 
532 #endif // SPOT_LTLAST_FORMULA_HH

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Thu May 15 2014 11:04:11 for spot by doxygen 1.8.4