Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
p_key.hh
1 // Copyright (C) 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_KEY_HH
27 # define MLN_CORE_SITE_SET_P_KEY_HH
28 
34 
35 # include <map>
36 # include <mln/core/concept/function.hh>
37 # include <mln/core/site_set/p_set.hh>
38 # include <mln/core/site_set/p_double.hh>
39 # include <mln/core/internal/site_set_base.hh>
40 # include <mln/util/ord.hh>
41 
42 
43 namespace mln
44 {
45 
46  // Forward declaration.
47  template <typename K, typename P> class p_key;
48 
49 
50 
51  namespace trait
52  {
53 
54  template <typename K, typename P>
55  struct site_set_< p_key<K,P> >
56  {
57  typedef trait::site_set::nsites::known nsites;
58  typedef trait::site_set::bbox::unknown bbox;
59  typedef trait::site_set::contents::growing contents;
60  typedef trait::site_set::arity::unique arity;
61  };
62 
63  } // end of namespace trait
64 
65 
66 
67 
71  template <typename K, typename P>
72  class p_key : public internal::site_set_base_< P,
73  p_key<K,P> >
74  {
75  typedef p_key<K,P> self_;
76  public:
77 
79  typedef P element;
80 
81 
83  typedef p_double_psite< self_, p_set<P> > psite;
84 
86  typedef p_double_piter<self_,
87  mln_fwd_eiter(util::set<K>),
88  mln_fwd_piter(p_set<P>)> fwd_piter;
89 
91  typedef p_double_piter<self_,
92  mln_bkd_eiter(util::set<K>),
93  mln_bkd_piter(p_set<P>)> bkd_piter;
94 
96  typedef fwd_piter piter;
97 
98 
100  p_key();
101 
102 
104  bool has(const psite&) const;
105 
107  bool has(const P& p) const;
108 
109 
111  bool is_valid() const;
112 
114  unsigned nsites() const;
115 
116 
118  typedef std::pair<K,P> i_element;
119 
121  void insert(const i_element& k_p);
122 
124  void insert(const K& k, const P& p);
125 
126 
127  void unsafe_insert_(const K& k, const P& p);
128 
129 
130 
132  typedef P r_element;
133 
135  void remove(const P& p);
136 
138  void remove_key(const K& k);
139 
141  void change_key(const K& k, const K& new_k);
142 
144  template <typename F>
145  void change_keys(const Function_v2v<F>& f);
146 
147 
148 
150  void clear();
151 
152 
156  const p_set<P>& operator()(const K& key) const;
157 
159  const K& key(const P& p) const;
160 
162  const util::set<K>& keys() const;
163 
164 
166  bool exists_key(const K& key) const;
167 
168 
169  // Required by p_double-related classes.
170  const util::set<K>& set_1_() const;
171  const p_set<P>& set_2_(const K& key) const;
172 
173 
175  std::size_t memory_size() const;
176 
177  protected:
178 
179  // Bunch of keys.
180  util::set<K> b_;
181 
182  // Function: key k -> set of sites {p}.
183  typedef std::map<K, p_set<P>, util::ord<K> > s_t;
184  s_t s_;
185 
186  // Function: site p -> key k.
187  typedef std::map<P, K, util::ord<P> > k_t;
188  k_t k_;
189 
190  // Number of sites.
191  unsigned n_;
192 
193  // Run invariance tests and return the result.
194  bool run_() const;
195  };
196 
197 
198 
199  template <typename K, typename P>
200  std::ostream& operator<<(std::ostream& ostr, const p_key<K,P>& pk);
201 
202 
203 
204 # ifndef MLN_INCLUDE_ONLY
205 
206  template <typename K, typename P>
207  inline
209  {
210  n_ = 0;
211  mln_invariant(run_());
212  }
213 
214  template <typename K, typename P>
215  inline
216  bool
217  p_key<K,P>::has(const psite&) const
218  {
219  mln_invariant(run_());
220  // FIXME
221  return true;
222  }
223 
224  template <typename K, typename P>
225  inline
226  bool
227  p_key<K,P>::has(const P& p) const
228  {
229  mln_invariant(run_());
230  return k_.find(p) != k_.end();
231  }
232 
233  template <typename K, typename P>
234  inline
235  bool
237  {
238  mln_invariant(run_());
239  return true;
240  }
241 
242  template <typename K, typename P>
243  inline
244  unsigned
246  {
247  mln_invariant(run_());
248  return n_;
249  }
250 
251 
252  template <typename K, typename P>
253  inline
254  void
255  p_key<K,P>::unsafe_insert_(const K& k, const P& p)
256  {
257  s_[k].insert(p);
258  k_[p] = k;
259  ++n_;
260  b_.insert(k);
261  mln_invariant(run_());
262  }
263 
264 
265  template <typename K, typename P>
266  inline
267  void
268  p_key<K,P>::insert(const K& k, const P& p)
269  {
270  mln_invariant(run_());
271  typename k_t::iterator p_k = k_.find(p);
272  if (p_k != k_.end())
273  // p is already in this set (so n_ is unchanged).
274  {
275  K p_key = p_k->second;
276  mln_assertion(b_.has(p_key));
277  mln_assertion(s_[p_key].has(p));
278  if (p_key == k)
279  // No-op.
280  return;
281  // p moves from s_[p_key] to s_[k].
282  s_[p_key].remove(p);
283  s_[k].insert(p);
284  // Update key of p.
285  p_k->second = k;
286  }
287  else
288  // Actual insertion.
289  {
290  s_[k].insert(p);
291  k_[p] = k;
292  ++n_;
293  }
294  b_.insert(k);
295  mln_invariant(run_());
296  }
297 
298  template <typename K, typename P>
299  inline
300  void
302  {
303  this->insert(k_p.first, k_p.second); // Also test invariants.
304  }
305 
306  template <typename K, typename P>
307  inline
308  void
309  p_key<K,P>::remove(const P& p)
310  {
311  mln_invariant(run_());
312  typename k_t::iterator p_k = k_.find(p);
313 
314  if (p_k == k_.end())
315  // No-op because p does not belong to this site set.
316  return;
317 
318  K p_key = p_k->second;
319  mln_assertion(b_.has(p_key));
320 
321  // Update k_.
322  k_.erase(p_k);
323 
324  // Update s_.
325  typename s_t::iterator k_s = s_.find(p_key);
326  mln_assertion(k_s != s_.end()); // p_key found in s_.
327  p_set<P>& s = k_s->second;
328  mln_assertion(s.has(p)); // p is in s_[p_key].
329 
330  if (s.nsites() == 1)
331  {
332  // Clean up for p is the only site with p_key.
333  s_.erase(k_s);
334  b_.remove(p_key);
335  }
336  else
337  {
338  // Simple removal.
339  s.remove(p);
340  }
341 
342  // Update n_.
343  --n_;
344 
345  mln_invariant(run_());
346  }
347 
348  template <typename K, typename P>
349  inline
350  void
352  {
353  mln_invariant(run_());
354  typename s_t::iterator k_s = s_.find(k);
355 
356  if (k_s == s_.end())
357  // No-op because key k does not exist.
358  return;
359 
360  // Update b_.
361  b_.remove(k);
362 
363  // Update k_.
364  p_set<P>& s = k_s->second;
365  mln_piter(p_set<P>) p(s);
366  for_all(p)
367  k_.erase(p);
368 
369  // Update n_.
370  n_ -= s.nsites();
371 
372  // Update s_.
373  s_.erase(k_s);
374 
375  mln_invariant(run_());
376  }
377 
378 
379  template <typename K, typename P>
380  inline
381  void
382  p_key<K,P>::change_key(const K& k, const K& new_k)
383  {
384  mln_invariant(run_());
385 
386  if (new_k == k)
387  // No-op.
388  return;
389 
390  typename s_t::iterator k_s = s_.find(k);
391  if (k_s == s_.end())
392  // No-op because key k does not exist.
393  return;
394 
395  // Update b_.
396  b_.remove(k);
397  b_.insert(new_k);
398 
399  // Update k_.
400  p_set<P>& s = k_s->second;
401  if (s.nsites() < n_ / 10) // Few elements to be moved.
402  {
403  // s.nsites() iterations.
404  mln_piter(p_set<P>) p(s);
405  for_all(p)
406  k_[p] = new_k;
407  }
408  else
409  {
410  // n_ iterations.
411  typename k_t::iterator p_k;
412  for (p_k = k_.begin(); p_k != k_.end(); ++p_k)
413  if (p_k->second == k)
414  p_k->second = new_k;
415  }
416 
417  // Update s_.
418  s_[new_k] += s;
419  s_.erase(k_s);
420 
421  mln_invariant(run_());
422  }
423 
424  template <typename K, typename P>
425  template <typename F>
426  inline
427  void
429  {
430  mln_invariant(run_());
431 
432  const F& f = exact(f_);
433  std::map<K,K> lut;
434 
435  // Update b_.
436  {
437  util::set<K> new_b;
438  mln_eiter(util::set<K>) k(b_);
439  for_all(k)
440  new_b.insert(lut[k] = f(k));
441  b_ = new_b;
442  }
443 
444  // Update k_ and s_.
445  {
446  s_t new_s;
447  typename k_t::iterator p_k;
448  for (p_k = k_.begin(); p_k != k_.end(); ++p_k)
449  {
450  p_k->second = lut[p_k->second];
451  new_s[p_k->second].insert(p_k->first);
452  }
453  s_ = new_s;
454  }
455 
456  mln_invariant(run_());
457  }
458 
459  template <typename K, typename P>
460  inline
461  void
463  {
464  mln_invariant(run_());
465  b_.clear();
466  s_.clear();
467  k_.clear();
468  n_ = 0;
469  mln_invariant(run_());
470  }
471 
472  template <typename K, typename P>
473  inline
474  std::size_t
476  {
477  mln_invariant(run_());
478  return 0; // FIXME
479 // std::size_t mem_q = 0;
480 // typename std::map<P, Q>::const_iterator i;
481 // for (i = q_.begin(); i != q_.end(); ++i)
482 // mem_q += i->second.memory_size();
483 // return p_.memory_size() + sizeof(q_) + sizeof(n_);
484  }
485 
486  template <typename K, typename P>
487  inline
488  const p_set<P>&
489  p_key<K,P>::operator()(const K& key) const
490  {
491  static const p_set<P> nil_ = p_set<P>();
492  if (exists_key(key)) // Also test invariants.
493  return s_.find(key)->second;
494  else
495  return nil_;
496  }
497 
498  template <typename K, typename P>
499  inline
500  const K&
501  p_key<K,P>::key(const P& p) const
502  {
503  mln_invariant(run_());
504  mln_precondition(k_.find(p) != k_.end());
505  return k_.find(p)->second;
506  }
507 
508  template <typename K, typename P>
509  inline
510  const util::set<K>&
512  {
513  mln_invariant(run_());
514  return b_;
515  }
516 
517  template <typename K, typename P>
518  inline
519  bool
520  p_key<K,P>::exists_key(const K& key) const
521  {
522  mln_invariant(run_());
523  return b_.has(key);
524  }
525 
526  template <typename K, typename P>
527  inline
528  const util::set<K>&
529  p_key<K,P>::set_1_() const
530  {
531  return b_;
532  }
533 
534  template <typename K, typename P>
535  inline
536  const p_set<P>&
537  p_key<K,P>::set_2_(const K& key) const
538  {
539  mln_precondition(b_.has(key));
540  return s_.find(key)->second;
541  }
542 
543  template <typename K, typename P>
544  inline
545  bool
546  p_key<K,P>::run_() const
547  {
548  if (! implies(n_ == 0, b_.is_empty()))
549  {
550  std::cerr << "#1" << std::endl;
551  return false;
552  }
553 
554  if (b_.nelements() != s_.size())
555  {
556  // Containers b_ and s_ are not consistent in size!
557  std::cerr << "#2" << std::endl;
558  return false;
559  }
560 
561  if (k_.size() != n_)
562  {
563  // The number of entries in k_ is not n_!
564  std::cerr << "#3: k_.size=" << k_.size() << " n_=" << n_ << std::endl;
565  return false;
566  }
567 
568  unsigned n = 0;
569  mln_eiter(util::set<K>) key(b_);
570  for_all(key)
571  {
572  typename s_t::const_iterator k_s = s_.find(key);
573 
574  if (k_s == s_.end())
575  {
576  // This key is not found in s_!
577  std::cerr << "#4" << std::endl;
578  return false;
579  }
580 
581  const p_set<P>& s = k_s->second;
582 
583  if (s.nsites() == 0)
584  {
585  // The site set associated with this key is empty!
586  std::cerr << "#5" << std::endl;
587  return false;
588  }
589 
590  n += s.nsites();
591 
592  mln_piter(p_set<P>) p(s);
593  for_all(p) // For every site p with the current key w.r.t. s_.
594  {
595  typename k_t::const_iterator p_k = k_.find(p);
596 
597  if (p_k == k_.end())
598  {
599  // There is no key entry for p in k_!
600  std::cerr << "#6" << std::endl;
601  return false;
602  }
603 
604  if (p_k->second != key)
605  {
606  // We have an inconsistency for p between s_ and k_!
607  std::cerr << "#7" << std::endl;
608  return false;
609  }
610  }
611  }
612 
613  if (n != n_)
614  {
615  // The number of elements in s_ is not n_!
616  std::cerr << "#8" << std::endl;
617  return false;
618  }
619 
620  return true;
621  }
622 
623 
624 
625 
626 
627  // Operator<<.
628 
629  template <typename K, typename P>
630  std::ostream& operator<<(std::ostream& ostr, const p_key<K,P>& pk)
631  {
632  ostr << '{';
633  mln_fwd_eiter(util::set<K>) k(pk.keys());
634  for_all(k)
635  {
636  ostr << ' ' << k << ':';
637  ostr << pk.set_2_(k);
638  }
639  ostr << '}';
640  return ostr;
641  }
642 
643 # endif // ! MLN_INCLUDE_ONLY
644 
645 } // end of namespace mln
646 
647 
648 #endif // ! MLN_CORE_SITE_SET_P_KEY_HH