Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
p_priority.hh
1 // Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_CORE_SITE_SET_P_PRIORITY_HH
27 # define MLN_CORE_SITE_SET_P_PRIORITY_HH
28 
32 
33 # include <map>
34 # include <mln/core/site_set/p_double.hh>
35 # include <mln/core/internal/site_set_base.hh>
36 # include <mln/util/set.hh>
37 # include <mln/util/ord.hh>
38 
39 
40 namespace mln
41 {
42 
43  // Forward declaration.
44  template <typename P, typename Q> class p_priority;
45 
46 
47 
48  namespace trait
49  {
50 
51  template <typename P, typename Q>
52  struct site_set_< p_priority<P,Q> >
53  {
54  typedef trait::site_set::nsites::known nsites;
55  typedef trait::site_set::bbox::unknown bbox;
56  typedef trait::site_set::contents::growing contents;
57  typedef trait::site_set::arity::multiple arity;
58  };
59 
60  } // end of namespace trait
61 
62 
63 
64 
68 
75  template <typename P, typename Q>
76  class p_priority : public internal::site_set_base_< mln_site(Q),
77  p_priority<P,Q> >,
78  private mlc_is_a(Q, Site_Set)::check_t
79  {
80  typedef p_priority<P,Q> self_;
81  public:
82 
84  typedef mln_element(Q) element;
85 
86 
88  typedef p_double_psite<self_, Q> psite;
89 
91  typedef p_double_piter< self_,
92  mln_bkd_eiter(util::set<P>),
93  mln_fwd_piter(Q) > fwd_piter;
94 
96  typedef p_double_piter< self_,
97  mln_fwd_eiter(util::set<P>),
98  mln_bkd_piter(Q) > bkd_piter;
99 
101  typedef fwd_piter piter;
102 
103 
105  p_priority();
106 
108  bool has(const psite&) const;
109 
111  bool is_valid() const;
112 
114  unsigned nsites() const;
115 
116 
118  void push(const P& priority, const element& e);
119 
121  typedef std::pair<P, element> i_element;
122 
124  void insert(const i_element& p_e);
125 
127  void insert(const p_priority<P,Q>& other);
128 
129 
133  void pop();
134 
138  const mln_element(Q)& front() const;
139 
143  mln_element(Q) pop_front();
144 
145 
147  void clear();
148 
149 
153  const Q& operator()(const P& priority) const;
154 
156  const util::set<P>& priorities() const;
157 
159  bool exists_priority(const P& priority) const;
160 
163  const P highest_priority() const;
164 
167  const P lowest_priority() const;
168 
169 
170  // Required by p_double-related classes.
171  const util::set<P>& set_1_() const;
172  const Q& set_2_(const P& priority) const;
173 
174 
176  std::size_t memory_size() const;
177 
178 
179  protected:
180 
181  typedef std::map<P, Q, util::ord<P> > q_type_;
182 
183  util::set<P> p_;
184  q_type_ q_;
185  unsigned n_;
186 
187  // Run invariance tests and return the result.
188  bool run_() const;
189  };
190 
191 
192 
193  template <typename P, typename Q>
194  std::ostream& operator<<(std::ostream& ostr, const p_priority<P,Q>& pq);
195 
196 
197 
198 # ifndef MLN_INCLUDE_ONLY
199 
200  template <typename P, typename Q>
201  inline
203  {
204  n_ = 0;
205  mln_invariant(run_());
206  }
207 
208  template <typename P, typename Q>
209  inline
210  bool
211  p_priority<P,Q>::has(const psite&) const
212  {
213  mln_invariant(run_());
214  // FIXME
215  return true;
216  }
217 
218  template <typename P, typename Q>
219  inline
220  bool
222  {
223  mln_invariant(run_());
224  return true;
225  }
226 
227  template <typename P, typename Q>
228  inline
229  unsigned
231  {
232  mln_invariant(run_());
233  return n_;
234  }
235 
236  template <typename P, typename Q>
237  inline
238  void
239  p_priority<P,Q>::push(const P& priority, const element& e)
240  {
241  mln_invariant(run_());
242  p_.insert(priority); // No-op if this priority already exists.
243  q_[priority].push(e);
244  ++n_;
245  mln_invariant(run_());
246  }
247 
248  template <typename P, typename Q>
249  inline
250  void
251  p_priority<P,Q>::insert(const i_element& p_e)
252  {
253  this->push(p_e.first, p_e.second); // Also test invariants.
254  }
255 
256  template <typename P, typename Q>
257  inline
258  void
260  {
261  mln_invariant(run_());
262  typename q_type_::const_iterator i;
263  for (i = other.q_.begin(); i != other.q_.end(); ++i)
264  {
265  P priority = i->first;
266  p_.insert(priority);
267  const Q& q_p = i->second;
268  q_[priority] += q_p;
269  }
270  n_ += other.n_;
271  mln_invariant(run_());
272  }
273 
274  template <typename P, typename Q>
275  inline
276  void
278  {
279  mln_precondition(! this->is_empty()); // Also test invariants.
280  P prior = highest_priority();
281  q_[prior].pop();
282  if (q_[prior].is_empty())
283  {
284  q_.erase(prior);
285  p_.remove(prior);
286  }
287  --n_;
288  mln_invariant(run_());
289  }
290 
291  template <typename P, typename Q>
292  inline
293  const mln_element(Q)&
295  {
296  mln_precondition(! this->is_empty()); // Also test invariants.
297  q_type_& q__ = const_cast< q_type_& >(q_);
298  return q__[highest_priority()].front();
299  }
300 
301  template <typename P, typename Q>
302  inline
303  mln_element(Q)
304  p_priority<P,Q>::pop_front()
305  {
306  mln_precondition(! this->is_empty()); // Also test invariants.
307  // FIXME: can be speeded up, return const& when possible...
308  mln_element(Q) e = this->front();
309  this->pop();
310  return e;
311  }
312 
313  template <typename P, typename Q>
314  inline
315  void
317  {
318  mln_invariant(run_());
319  p_.clear();
320  q_.clear();
321  n_ = 0;
322  mln_invariant(run_());
323  }
324 
325  template <typename P, typename Q>
326  inline
327  std::size_t
329  {
330  mln_invariant(run_());
331  std::size_t mem_q = 0;
332  typename q_type_::const_iterator i;
333  for (i = q_.begin(); i != q_.end(); ++i)
334  mem_q += i->second.memory_size();
335  return p_.memory_size() + sizeof(q_) + sizeof(n_);
336  }
337 
338  template <typename P, typename Q>
339  inline
340  const Q&
341  p_priority<P,Q>::operator()(const P& priority) const
342  {
343  static const Q nil_ = Q();
344  if (exists_priority(priority)) // Also test invariants.
345  {
346  q_type_& mq = const_cast<q_type_&>(q_);
347  mln_assertion(mq[priority].nsites() > 0);
348  return mq[priority];
349  }
350  else
351  return nil_;
352  }
353 
354  template <typename P, typename Q>
355  inline
356  const util::set<P>&
358  {
359  mln_invariant(run_());
360  return p_;
361  }
362 
363  template <typename P, typename Q>
364  inline
365  bool
366  p_priority<P,Q>::exists_priority(const P& priority) const
367  {
368  mln_invariant(run_());
369  return p_.has(priority);
370  }
371 
372  template <typename P, typename Q>
373  inline
374  const P
376  {
377  mln_precondition(! this->is_empty()); // Also test invariants.
378  return p_.last_element();
379  }
380 
381  template <typename P, typename Q>
382  inline
383  const P
385  {
386  mln_precondition(! this->is_empty()); // Also test invariants.
387  return p_.first_element();
388  }
389 
390  template <typename P, typename Q>
391  inline
392  const util::set<P>&
394  {
395  return p_;
396  }
397 
398  template <typename P, typename Q>
399  inline
400  const Q&
401  p_priority<P,Q>::set_2_(const P& priority) const
402  {
403  mln_precondition(p_.has(priority));
404  q_type_& mq = const_cast<q_type_&>(q_);
405  mln_precondition(mq[priority].nsites() > 0);
406  return mq[priority];
407  }
408 
409  template <typename P, typename Q>
410  inline
411  bool
412  p_priority<P,Q>::run_() const
413  {
414  if (! implies(n_ == 0, p_.is_empty()))
415  return false;
416 
417  if (! (p_.nelements() == q_.size()))
418  // Containers p_ and q_ are not consistent in size!
419  return false;
420 
421  mln_eiter(util::set<P>) p(p_);
422  for_all(p)
423  if (q_.find(p) == q_.end())
424  // We have an empty queue (with priority p)!
425  return false;
426 
427  typename std::map<P,Q>::const_iterator i;
428  for (i = q_.begin(); i != q_.end(); ++i)
429  if (! p_.has(i->first))
430  // A priority is unknown (for a known queue)!
431  return false;
432 
433  return true;
434  }
435 
436 
437  // Operator<<.
438 
439  template <typename P, typename Q>
440  std::ostream& operator<<(std::ostream& ostr, const p_priority<P,Q>& pq)
441  {
442  ostr << '{';
443  mln_bkd_eiter(util::set<P>) p(pq.priorities());
444  for_all(p)
445  {
446  ostr << ' ' << p << ':';
447  ostr << pq.set_2_(p);
448  }
449  ostr << '}';
450  return ostr;
451  }
452 
453 # endif // ! MLN_INCLUDE_ONLY
454 
455 } // end of namespace mln
456 
457 
458 #endif // ! MLN_CORE_SITE_SET_P_PRIORITY_HH