tgbaexplicit.hh 11 KB
Newer Older
1
// Copyright (C) 2009, 2010, 2011 Laboratoire de Recherche et Développement
Guillaume Sadegh's avatar
Guillaume Sadegh committed
2
3
// de l'Epita (LRDE).
// Copyright (C) 2003, 2004, 2006 Laboratoire d'Informatique de
4
5
// Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
// Université Pierre et Marie Curie.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
// This file is part of Spot, a model checking library.
//
// Spot is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Spot is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
// License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Spot; see the file COPYING.  If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.

24
25
26
#ifndef SPOT_TGBA_TGBAEXPLICIT_HH
# define SPOT_TGBA_TGBAEXPLICIT_HH

27
#include "misc/hash.hh"
28
29
30
#include <list>
#include "tgba.hh"
#include "ltlast/formula.hh"
31
#include <cassert>
32
33
34
35
36
37

namespace spot
{
  // Forward declarations.  See below.
  class state_explicit;
  class tgba_explicit_succ_iterator;
38
  class tgba_explicit;
39

40
  /// States used by spot::tgba_explicit.
41
  /// \ingroup tgba_representation
42
  class state_explicit: public spot::state
43
44
  {
  public:
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    state_explicit()
    {
    }

    virtual int compare(const spot::state* other) const;
    virtual size_t hash() const;

    virtual state_explicit* clone() const
    {
      return const_cast<state_explicit*>(this);
    }

    bool empty() const
    {
      return successors.empty();
    }
61

62
63
64
65
    virtual
    void destroy() const
    {
    }
66

67
    /// Explicit transitions.
68
69
70
    struct transition
    {
      bdd condition;
71
      bdd acceptance_conditions;
72
      const state_explicit* dest;
73
74
    };

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
    typedef std::list<transition> transitions_t;
    transitions_t successors;
  private:
    state_explicit(const state_explicit& other);
    state_explicit& operator=(const state_explicit& other);

    virtual ~state_explicit()
    {
    }
    friend class tgba_explicit_string;
    friend class tgba_explicit_formula;
    friend class tgba_explicit_number;
  };


  /// Explicit representation of a spot::tgba.
  /// \ingroup tgba_representation
  class tgba_explicit: public tgba
  {
  public:
    typedef state_explicit state;
    typedef state_explicit::transition transition;

    tgba_explicit(bdd_dict* dict);

100
101
    /// Add a default initial state.
    virtual state* add_default_init() = 0;
102

103
104
    transition*
    create_transition(state* source, const state* dest);
105

106
    void add_condition(transition* t, const ltl::formula* f);
107
108
    /// This assumes that all variables in \a f are known from dict.
    void add_conditions(transition* t, bdd f);
109
110
111
112
113
114
115

    /// \brief Copy the acceptance conditions of a tgba.
    ///
    /// If used, this function should be called before creating any
    /// transition.
    void copy_acceptance_conditions_of(const tgba *a);

116
117
118
    /// The the acceptance conditions.
    void set_acceptance_conditions(bdd acc);

119
120
121
122
    bool has_acceptance_condition(const ltl::formula* f) const;
    void add_acceptance_condition(transition* t, const ltl::formula* f);
    /// This assumes that all acceptance conditions in \a f are known from dict.
    void add_acceptance_conditions(transition* t, bdd f);
123

124
125
126
127
    // tgba interface
    virtual ~tgba_explicit();
    virtual spot::state* get_init_state() const;
    virtual tgba_succ_iterator*
128
129
130
    succ_iter(const spot::state* local_state,
	      const spot::state* global_state = 0,
	      const tgba* global_automaton = 0) const;
131
    virtual bdd_dict* get_dict() const;
132

133
134
    virtual bdd all_acceptance_conditions() const;
    virtual bdd neg_acceptance_conditions() const;
135

136
137
    virtual std::string format_state(const spot::state* s) const = 0;

138
  protected:
139
140
141
    virtual bdd compute_support_conditions(const spot::state* state) const;
    virtual bdd compute_support_variables(const spot::state* state) const;

142
    bdd get_acceptance_condition(const ltl::formula* f);
143

144
    bdd_dict* dict_;
145
    state_explicit* init_;
146
147
148
    mutable bdd all_acceptance_conditions_;
    bdd neg_acceptance_conditions_;
    mutable bool all_acceptance_conditions_computed_;
149
150
151
152

  private:
    // Disallow copy.
    tgba_explicit(const tgba_explicit& other);
153
    tgba_explicit& operator=(const tgba_explicit& other);
154
155
156
  };


157

158
  /// Successor iterators used by spot::tgba_explicit.
159
  /// \ingroup tgba_representation
160
  class tgba_explicit_succ_iterator: public tgba_succ_iterator
161
162
  {
  public:
163
164
    tgba_explicit_succ_iterator(const state_explicit::transitions_t* s,
				bdd all_acc);
165
166
167

    virtual void first();
    virtual void next();
168
    virtual bool done() const;
169

170
171
    virtual state_explicit* current_state() const;
    virtual bdd current_condition() const;
172
    virtual bdd current_acceptance_conditions() const;
173
174

  private:
175
176
    const state_explicit::transitions_t* s_;
    state_explicit::transitions_t::const_iterator i_;
177
    bdd all_acceptance_conditions_;
178
179
  };

180
181
182
183
184
185
  /// A tgba_explicit instance with states labeled by a given type.
  template<typename label, typename label_hash>
  class tgba_explicit_labelled: public tgba_explicit
  {
  protected:
    typedef label label_t;
186
    typedef Sgi::hash_map<label, state_explicit*,
187
			  label_hash> ns_map;
188
189
    typedef Sgi::hash_map<const state_explicit*, label,
			  ptr_hash<state_explicit> > sn_map;
190
191
192
193
194
195
196
197
198
199
    ns_map name_state_map_;
    sn_map state_name_map_;
  public:
    tgba_explicit_labelled(bdd_dict* dict) : tgba_explicit(dict) {};

    bool has_state(const label& name)
    {
      return name_state_map_.find(name) != name_state_map_.end();
    }

200
    const label& get_label(const state_explicit* s) const
201
202
203
204
205
206
207
208
    {
      typename sn_map::const_iterator i = state_name_map_.find(s);
      assert(i != state_name_map_.end());
      return i->second;
    }

    const label& get_label(const spot::state* s) const
    {
209
      const state_explicit* se = down_cast<const state_explicit*>(s);
210
      assert(se);
211
      return get_label(se);
212
213
    }

214
    /// Return the state_explicit for \a name, creating the state if
215
216
217
218
219
220
    /// it does not exist.
    state* add_state(const label& name)
    {
      typename ns_map::iterator i = name_state_map_.find(name);
      if (i == name_state_map_.end())
	{
221
	  state_explicit* s = new state_explicit;
222
223
224
225
226
227
228
229
230
231
232
233
	  name_state_map_[name] = s;
	  state_name_map_[s] = name;

	  // The first state we add is the inititial state.
	  // It can also be overridden with set_init_state().
	  if (!init_)
	    init_ = s;

	  return s;
	}
      return i->second;
    }
234

235
236
237
    state*
    set_init_state(const label& state)
    {
238
      state_explicit* s = add_state(state);
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
      init_ = s;
      return s;
    }


    transition*
    create_transition(state* source, const state* dest)
    {
      return tgba_explicit::create_transition(source, dest);
    }

    transition*
    create_transition(const label& source, const label& dest)
    {
      // It's important that the source be created before the
      // destination, so the first source encountered becomes the
      // default initial state.
      state* s = add_state(source);
      return tgba_explicit::create_transition(s, add_state(dest));
    }

    void
    complement_all_acceptance_conditions()
    {
      bdd all = all_acceptance_conditions();
      typename ns_map::iterator i;
      for (i = name_state_map_.begin(); i != name_state_map_.end(); ++i)
	{
267
268
269
	  state_explicit::transitions_t::iterator i2;
	  for (i2 = i->second->successors.begin();
	       i2 != i->second->successors.end(); ++i2)
270
	    {
271
	      i2->acceptance_conditions = all - i2->acceptance_conditions;
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
	    }
	}
    }

    void
    declare_acceptance_condition(const ltl::formula* f)
    {
      int v = dict_->register_acceptance_variable(f, this);
      f->destroy();
      bdd neg = bdd_nithvar(v);
      neg_acceptance_conditions_ &= neg;

      // Append neg to all acceptance conditions.
      typename ns_map::iterator i;
      for (i = name_state_map_.begin(); i != name_state_map_.end(); ++i)
	{
288
289
290
291
	  state_explicit::transitions_t::iterator i2;
	  for (i2 = i->second->successors.begin();
	       i2 != i->second->successors.end(); ++i2)
	    i2->acceptance_conditions &= neg;
292
293
294
295
296
297
298
299
300
301
302
303
	}

      all_acceptance_conditions_computed_ = false;
    }


    void
    merge_transitions()
    {
      typename ns_map::iterator i;
      for (i = name_state_map_.begin(); i != name_state_map_.end(); ++i)
	{
304
305
306
	  state_explicit::transitions_t::iterator t1;
	  for (t1 = i->second->successors.begin();
	       t1 != i->second->successors.end(); ++t1)
307
	    {
308
309
	      bdd acc = t1->acceptance_conditions;
	      const state* dest = t1->dest;
310
311
312

	      // Find another transition with the same destination and
	      // acceptance conditions.
313
	      state_explicit::transitions_t::iterator t2 = t1;
314
	      ++t2;
315
	      while (t2 != i->second->successors.end())
316
		{
317
318
319
		  state_explicit::transitions_t::iterator t2copy = t2++;
		  if (t2copy->acceptance_conditions == acc
		      && t2copy->dest == dest)
320
		    {
321
322
		      t1->condition |= t2copy->condition;
		      i->second->successors.erase(t2copy);
323
324
325
326
327
328
329
330
331
332
		    }
		}
	    }
	}
    }


    virtual
    ~tgba_explicit_labelled()
    {
333
334
335
336
      // These have already been destroyed by subclasses.
      // Prevent destroying by tgba::~tgba.
      last_support_conditions_input_ = 0;
      last_support_variables_input_ = 0;
337
338
339
340
    }

  };

341
#ifndef SWIG
342
343
344
345
346
347
348
  class tgba_explicit_string:
    public tgba_explicit_labelled<std::string, string_hash>
  {
  public:
    tgba_explicit_string(bdd_dict* dict):
      tgba_explicit_labelled<std::string, string_hash>(dict)
    {};
349
    virtual ~tgba_explicit_string();
350
351
    virtual state* add_default_init();
    virtual std::string format_state(const spot::state* s) const;
352
353
354
355

    /// Create an alias for a state.  Any reference to \a alias_name
    /// will act as a reference to \a real_name.
    virtual
356
    void add_state_alias(const std::string& alias_name,
357
358
359
360
			 const std::string& real_name)
    {
      name_state_map_[alias_name] = add_state(real_name);
    }
361
  };
362
363
364
365
366
#else
  class tgba_explicit_string: public tgba
  {
  };
#endif
367

368
#ifndef SWIG
369
370
371
372
373
374
375
376
377
378
379
  class tgba_explicit_formula:
    public tgba_explicit_labelled<const ltl::formula*, ltl::formula_ptr_hash>
  {
  public:
    tgba_explicit_formula(bdd_dict* dict):
      tgba_explicit_labelled<const ltl::formula*, ltl::formula_ptr_hash>(dict)
    {};
    virtual ~tgba_explicit_formula();
    virtual state* add_default_init();
    virtual std::string format_state(const spot::state* s) const;
  };
380
381
382
383
384
#else
  class tgba_explicit_formula: public tgba
  {
  };
#endif
385

386
#ifndef SWIG
387
  class tgba_explicit_number:
388
    public tgba_explicit_labelled<int, identity_hash<int> >
389
390
391
  {
  public:
    tgba_explicit_number(bdd_dict* dict):
392
      tgba_explicit_labelled<int, identity_hash<int> >(dict)
393
394
395
396
397
    {};
    virtual ~tgba_explicit_number();
    virtual state* add_default_init();
    virtual std::string format_state(const spot::state* s) const;
  };
398
399
400
401
402
#else
  class tgba_explicit_number: public tgba
  {
  };
#endif
403
404
405
}

#endif // SPOT_TGBA_TGBAEXPLICIT_HH