Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
dual_hqueue.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_MORPHO_TREE_IMPL_COMPUTE_PARENT_DUAL_HQUEUE_HH
27 # define MLN_MORPHO_TREE_IMPL_COMPUTE_PARENT_DUAL_HQUEUE_HH
28 
45 
46 # include <mln/data/sort_psites.hh>
47 # include <mln/data/fill.hh>
48 
49 # include <mln/geom/nsites.hh>
50 # include <mln/geom/translate.hh>
51 
52 # include <mln/morpho/tree/data.hh>
53 
54 # include <mln/util/hqueues.hh>
55 # include <mln/util/ord.hh>
56 
57 # include <mln/value/value_array.hh>
58 # include <mln/value/set.hh>
59 
60 # include <mln/util/timer.hh>
61 
62 namespace mln
63 {
64 
65  namespace morpho
66  {
67 
68  namespace tree
69  {
70 
71  namespace impl
72  {
73 
82  template <typename I, typename N>
83  inline
85  dual_hqueue(const Image<I>& f,
86  const Image<I>& m,
87  const Neighborhood<N>& nbh);
88 
89  } // end of namespace mln::morpho::tree::impl
90 
91 
92 # ifndef MLN_INCLUDE_ONLY
93 
94  namespace internal
95  {
96 
97  template <typename I, typename N, class E>
98  struct shared_flood_args
99  {
100  typedef mln_psite(I) P;
101  typedef mln_value(I) V;
102  typedef p_array<P> S;
103 
104  const I& f;
105  const I& m;
106  const N& nbh;
107  mln_ch_value(I, P)& parent;
108 
109  // Aux data
110  util::hqueues<P, V>& hqueues;
111  const E& extend; // site -> site functor.
112  value::value_array<V, bool> is_node_at_level;
113  value::value_array<V, P> node_at_level;
114  mln_ch_value(I, bool) deja_vu;
115  const value::set<V>& vset;
116 
117  shared_flood_args(const I& f_,
118  const I& m_,
119  const N& neigb_,
120  mln_ch_value(I, P)& parent_,
121  util::hqueues<mln_psite(I), V>& hqueues_,
122  const E& extend_)
123  : f (f_),
124  m (m_),
125  nbh (neigb_),
126  parent (parent_),
127  hqueues (hqueues_),
128  extend (extend_),
129  is_node_at_level (false),
130  vset (hqueues.vset())
131  {
132  initialize(deja_vu, f);
133  mln::data::fill(deja_vu, false);
134  }
135  };
136 
137  template <typename I>
138  inline
139  histo::array<mln_value(I)>
140  compute_histo(const I& f, const I& m, mln_value(I)& hmin, mln_psite(I)& pmin)
141  {
142  histo::array<mln_value(I)> hm = histo::compute(m);
143  const histo::array<mln_value(I)> hf = histo::compute(f);
144 
145  { // Retrieve hmin.
146  unsigned i = 0;
147  while (hm[i] == 0)
148  ++i;
149  hmin = hm.vset()[i];
150  }
151 
152  // Merge histograms.
153  for (unsigned i = 0; i < hm.nvalues(); ++i)
154  hm[i] += hf[i];
155 
156  // Retrieve pmin.
157  mln_piter(I) p(m.domain());
158  for (p.start(); m(p) != hmin; p.next())
159  ;
160  mln_assertion(p.is_valid());
161  pmin = p;
162 
163  return hm;
164  }
165 
166  // Site -> site functor: give for all p in Domain(f), its
167  // equivalence in the extended domain.
168  // TODO: make it generic. It works only on boxed domain.
169  template <typename I>
170  struct extend
171  {
172  extend(const mln_psite(I)::delta& dp)
173  : dp_ (dp)
174  {
175  }
176 
177  mln_psite(I) operator() (const mln_psite(I)& p) const
178  {
179  return p + dp_;
180  }
181 
182  private:
183  const mln_psite(I)::delta dp_;
184  };
185 
186  } // end of namespace mln::morpho::tree::internal
187 
188  namespace impl
189  {
190 
191  template <typename I, typename N, typename E>
192  unsigned
193  flood(internal::shared_flood_args<I, N, E>& args, const unsigned h_idx)
194  {
195  mln_assertion(args.is_node_at_level[h_idx]);
196 
197  while (!args.hqueues[h_idx].empty())
198  {
199  mln_psite(I) p = args.hqueues[h_idx].pop_front();
200  unsigned p_idx = args.vset.index_of(args.f(p));
201 
202  if (p_idx != h_idx)
203  { // Intensity mismatch: irregular case.
204  mln_psite(I) pext = args.extend(p);
205  args.parent(pext) = args.node_at_level[h_idx];
206 
207  if (p_idx > h_idx) // Singleton with parent at h.
208  args.parent(p) = args.node_at_level[h_idx];
209  else
210  {
211  if (!args.is_node_at_level[p_idx])
212  {
213  args.is_node_at_level[p_idx] = true;
214  args.node_at_level[p_idx] = p;
215  }
216  }
217  }
218 
219  if (p_idx <= h_idx)
220  {
221  if (!args.f.domain().has(args.node_at_level[p_idx]) ||
222  util::ord_strict(p, args.node_at_level[p_idx]))
223  { // Regular case but a representative provided by the extension.
224  args.parent(args.node_at_level[p_idx]) = p;
225  args.node_at_level[p_idx] = p;
226  //args.parent(p) = p;
227  }
228  args.parent(p) = args.node_at_level[p_idx];
229  }
230 
231 
232  // Process the neighbors
233  mln_niter(N) n(args.nbh, p);
234  for_all(n)
235  if (args.f.domain().has(n) && !args.deja_vu(n))
236  {
237  unsigned mn = args.vset.index_of(args.m(n));
238  unsigned fn = args.vset.index_of(args.f(n));
239  args.hqueues[mn].push(n);
240  args.deja_vu(n) = true;
241 
242  mln_psite(I) ext = args.extend(n);
243  // Create a node at c.
244  {
245  mln_psite(I) node = (fn == mn) ? n : ext;
246  if (!args.is_node_at_level[mn])
247  {
248  args.is_node_at_level[mn] = true;
249  args.node_at_level[mn] = node;
250  }
251  }
252 
253  while (mn > h_idx)
254  mn = flood(args, mn);
255  }
256  }
257 
258  // Retrieve dad.
259  args.is_node_at_level[h_idx] = false;
260  unsigned c = h_idx;
261  while (c > 0 && !args.is_node_at_level[c])
262  --c;
263 
264  mln_psite(I) x = args.node_at_level[h_idx];
265  if (c > 0)
266  args.parent(x) = args.node_at_level[c];
267  else
268  args.parent(x) = x;
269 
270  return c;
271  }
272 
273  template <typename I, typename N>
274  inline
275  data< I, p_array<mln_psite(I)> >
276  dual_hqueue(const Image<I>& f_,
277  const Image<I>& m_,
278  const Neighborhood<N>& neibh_)
279  {
280  trace::entering("mln::morpho::tree::impl::dual_hqueue");
281 
282  const I& f = exact(f_);
283  const I& m = exact(m_);
284  const N& nbh = exact(neibh_);
285 
286  typedef mln_psite(I) P;
287  typedef p_array<mln_psite(I)> S;
288 
289  util::timer tm;
290  tm.start();
291 
292  // Histo.
293  mln_psite(I) pmin;
294  mln_value(I) hmin;
295  const histo::array<mln_value(I)> histo = internal::compute_histo(f, m, hmin, pmin);
296  util::hqueues<P, mln_value(I)> hqueues(histo);
297 
298  mln_psite(I)::delta dp(literal::zero);
299  mln_domain(I) d_ext = f.domain();
300  mln_domain(I) d = f.domain();
301 
302  // Extend the domain.
303  dp[0] = d.pmax()[0] - d.pmin()[0] + 1;
304  d.pmax() += dp;
305  d_ext.pmin() += dp;
306  d_ext.pmax() += dp;
307 
308  // Data.
309  mln_concrete(I) fext;
310  mln_ch_value(I, P) parent;
311  p_array<mln_psite(I)> s;
312 
313  // Initialization.
314  fext = geom::translate(m, dp.to_vec(), f, d);
315  initialize(parent, fext);
316  s.reserve(geom::nsites(fext));
317 
318  // Process.
319  internal::extend<I> extend(dp);
320  internal::shared_flood_args< I, N, internal::extend<I> >
321  args(f, m, nbh, parent, hqueues, extend);
322 
323  unsigned r = args.vset.index_of(hmin);
324  args.deja_vu(pmin) = true;
325  args.hqueues[r].push(pmin);
326  args.node_at_level[r] = (f(pmin) == hmin) ? pmin : extend(pmin);
327  args.is_node_at_level[r] = true;
328  flood(args, r);
329 
330  // Attach the nodes under hmin.
331  unsigned i = r;
332  do
333  {
334  if (args.is_node_at_level[i])
335  {
336  parent(args.node_at_level[r]) = args.node_at_level[i];
337  r = i;
338  }
339  }
340  while (i-- > 0);
341  parent(args.node_at_level[r]) = args.node_at_level[r]; //root
342 
343  // Canonization and make tree site set.
344  {
345  mln_ch_value(I, bool) deja_vu(d_ext);
346  mln::data::fill(deja_vu, false);
347 
348  p_array<mln_psite(I)> s_f = mln::data::sort_psites_increasing(f);
349  mln_fwd_piter(S) p(s_f); // Forward.
350  for_all(p)
351  {
352  P x = p;
353  P q = parent(p);
354 
355  // Case: l: m <---- m <---- f
356  // Or
357  // Case l1: m <----- f impossible.
358  // |
359  // l2: m
360  mln_assertion(!(d_ext.has(q) && fext(p) == fext(q) && d_ext.has(parent(q)) && q != parent(q)));
361 
362  while (d_ext.has(q) && !deja_vu(q) && (fext(q) != fext(parent(q)) || q == parent(q)))
363  {
364  s.append(q);
365  deja_vu(q) = true;
366  x = q;
367  q = parent(q);
368  }
369 
370  if (d_ext.has(q) && fext(q) == fext(parent(q)) && q != parent(q))
371  {
372  q = (parent(x) = parent(q));
373  mln_assertion(f.domain().has(q));
374  }
375 
376  if (fext(q) == fext(parent(q)))
377  parent(x) = parent(q);
378 
379  s.append(p);
380 
381  mln_assertion((q = parent(p)) == parent(q) || fext(q) != fext(parent(q)));
382  }
383 
384  }
385 
386  std::cout << "Construction de l'arbre en " << tm << " s." << std::endl;
387 
388  data<I, S> tree(fext, parent, s);
389 
390  trace::exiting("mln::morpho::tree::impl::dual_hqueue");
391 
392  return tree;
393  }
394 
395  } // end of namespace mln::morpho::tree::impl
396 
397 # endif // ! MLN_INCLUDE_ONLY
398 
399  } // end of namespace mln::morpho::tree
400 
401  } // end of namespace mln::morpho
402 
403 } // end of namespace mln
404 
405 #endif // !MLN_MORPHO_TREE_COMPUTE_PARENT_DUAL_HQUEUE_HH
406 
407 
408