Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
dual_union_find.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_IMLP_DUAL_UNION_FIND_HH
27 # define MLN_MORPHO_TREE_IMLP_DUAL_UNION_FIND_HH
28 
40 
41 # include <mln/data/fill.hh>
42 
43 # include <mln/geom/nsites.hh>
44 # include <mln/geom/translate.hh>
45 
46 # include <mln/morpho/tree/data.hh>
47 
48 # include <mln/util/timer.hh>
49 
50 namespace mln
51 {
52 
53  namespace morpho
54  {
55 
56  namespace tree
57  {
58 
59  namespace impl
60  {
61 
62  namespace generic
63  {
64 
75  template <typename I, typename S, typename N>
77  dual_union_find(const Image<I>& f,
78  const Image<I>& m,
79  const Site_Set<S>& s_f,
80  const Site_Set<S>& s_m,
81  const Neighborhood<N>& nbh);
82 
83  } // end of namespace mln::morpho::tree::impl::generic
84 
85  } // end of namespace mln::morpho::tree::impl
86 
87 # ifndef MLN_INCLUDE_ONLY
88 
89  namespace internal
90  {
91  // For benchmark purpose. More than 50% of the time is spent
92  // in find_root function.
93  static util::timer t_prop;
94 
95 
96  template <typename I>
97  inline
98  mln_psite(I) find_root(I& zpar,
99  const mln_psite(I)& p)
100  {
101  if (zpar(p) == p)
102  return p;
103 
104  t_prop.resume();
105  mln_psite(I) x = zpar(p);
106  while (zpar(x) != x)
107  x = zpar(x);
108 
109  mln_psite(I) tmp;
110  for (mln_psite(I) y = p; y != x; y = tmp)
111  {
112  tmp = zpar(y);
113  zpar(y) = x;
114  }
115  t_prop.stop();
116 
117  return x;
118  }
119 
120  template <typename I>
121  inline
122  void
123  update_m_parent(const I& f,
124  mln_ch_value(I, mln_psite(I))& parent,
125  mln_ch_value(I, bool)& deja_vu,
126  p_array< mln_psite(I) >& sset,
127  const mln_domain(I)& d_ext,
128  const mln_psite(I)& p)
129  {
130  typedef mln_psite(I) P;
131 
132  P q = parent(p);
133  P x = parent(q);
134 
135  mln_assertion(d_ext.has(q));
136 
137  while (d_ext.has(x) && f(q) == f(x) && q != x)
138  {
139  q = x;
140  x = parent(q);
141  }
142 
143  if (!d_ext.has(x))
144  {
145  if (f(x) == f(parent(x)))
146  x = (parent(q) = parent(x));
147  if (f(q) != f(x))
148  {
149  x = q;
150  if (!deja_vu(q))
151  {
152  deja_vu(q) = true;
153  sset.append(q);
154  }
155  }
156 
157  }
158  else
159  {
160  if (x != q)
161  {
162  update_m_parent(f, parent, deja_vu, sset, d_ext, q);
163  x = q;
164  }
165  if (!deja_vu(q))
166  {
167  deja_vu(q) = true;
168  sset.append(q);
169  }
170  }
171 
172  for (P i = p, tmp = parent(i); i != q; i = tmp, tmp = parent(i))
173  parent(i) = x;
174  }
175 
176  } // end of namespace mln::morpho::tree::internal
177 
178  namespace impl
179  {
180 
181  namespace generic
182  {
183 
184 
185  template <typename I, typename S, typename N>
187  dual_union_find(const Image<I>& f_,
188  const Image<I>& m_,
189  const Site_Set<S>& s_f_,
190  const Site_Set<S>& s_m_,
191  const Neighborhood<N>& nbh_)
192  {
193  trace::entering("morpho::tree::impl::generic::dual_union_find");
194 
195  util::timer tm;
196  tm.start();
197  internal::t_prop.reset();
198 
199  typedef mln_psite(I) P;
200  typedef unsigned L;
201 
202  const I& f = exact(f_);
203  const I& m = exact(m_);
204  const S& s_f = exact(s_f_);
205  const S& s_m = exact(s_m_);
206  const N& nbh = exact(nbh_);
207 
208  // Aux data.
209  mln_psite(I)::delta dp(literal::zero);
210  mln_domain(I) d_f = f.domain();
211  mln_domain(I) d_ext = f.domain(); // translate dp
212  mln_domain(I) d = f.domain();
213 
214  // Extend the domain.
215  dp[0] = d.pmax()[0] - d.pmin()[0] + 1;
216  d.pmax() += dp;
217  d_ext.pmin() += dp;
218  d_ext.pmax() += dp;
219 
220  // Data.
221  mln_concrete(I) fext;
222  mln_ch_value(I, P) parent;
223  p_array<mln_psite(I)> s;
224 
225  // Initialization.
226  fext = geom::translate(m, dp.to_vec(), f, d);
227  initialize(parent, fext);
228  s.reserve(geom::nsites(fext));
229 
230  //Process
231  {
232  // Aux data.
233  mln_ch_value(I, bool) deja_vu;
234  mln_ch_value(I, P) zpar;
235 
236  initialize(deja_vu, fext);
237  initialize(zpar, fext);
238  mln::data::fill(deja_vu, false);
239 
240  mln_bkd_piter(S) p_f(s_f); // Backward.
241  mln_bkd_piter(S) p_m(s_m); // Backward.
242  p_f.start();
243  p_m.start();
244 
245  // Main loop.
246  while (p_m.is_valid() || p_f.is_valid())
247  {
248  mln_bkd_piter(S)& it = (!p_f.is_valid() || (p_m.is_valid() && f(p_f) <= m(p_m))) ? p_m : p_f;
249 
250  P p = it;
251  P ext = p + dp;
252 
253  // std::cout << "-------------------" << std::endl;
254  // std::cout << "Take " << p << " of value " << (&it == &p_m ? m(p) : f(p))
255  // << " from " << (&it == &p_m ? "mask" : "f") << std::endl;
256  // debug::println("Parent: ", parent);
257  // debug::println("Zpar: ", zpar);
258 
259  mln_assertion(!(deja_vu(p) && deja_vu(ext)));
260  if (deja_vu(ext)) // Seen by mask before f.
261  {
262  mln_assertion(m(p) >= f(p));
263  // Make set.
264  parent(p) = p;
265  zpar(p) = p;
266 
267  P r = internal::find_root(zpar, ext);
268  zpar(r) = p;
269  parent(r) = p;
270 
271  deja_vu(p) = true;
272  }
273  else if (deja_vu(p)) // Seen by f before mask.
274  {
275  mln_assertion(f(p) > m(p));
276  parent(p) = ext;
277  zpar(p) = ext;
278  parent(ext) = ext;
279  zpar(ext) = ext;
280 
281  mln_niter(N) n(nbh, ext);
282  for_all(n)
283  if (d_ext.has(n) && deja_vu(n))
284  {
285  P r = internal::find_root(zpar, n);
286  //std::cout << "Root: " << r << std::endl;
287  if (r != ext)
288  {
289  parent(r) = ext;
290  zpar(r) = ext;
291  }
292  }
293  deja_vu(ext) = true;
294  }
295  else if (f(p) <= m(p)) // First time p encountered.
296  {
297  zpar(ext) = ext;
298  mln_niter(N) n(nbh, ext);
299  for_all(n)
300  if (d_ext.has(n) && deja_vu(n))
301  {
302  P r = internal::find_root(zpar, n);
303  if (r != ext)
304  {
305  zpar(r) = ext;
306  parent(r) = ext;
307  }
308  }
309  deja_vu(ext) = true;
310  }
311  else
312  {
313  deja_vu(p) = true;
314  }
315  it.next();
316  }
317  }
318  std::cout << ">> MAJ zpar: " << internal::t_prop << " s" << std::endl;
319  std::cout << "Parent construction: " << tm << " s" << std::endl;
320  tm.restart();
321 
322  // Canonization
323  {
324  mln_ch_value(I, bool) deja_vu(d_ext);
325  mln::data::fill(deja_vu, false);
326  mln_fwd_piter(S) p(s_f); // Forward.
327  for_all(p)
328  {
329  P q = parent(p);
330  if (!f.domain().has(q))
331  internal::update_m_parent(fext, parent, deja_vu, s, d_ext, p);
332  else if (fext(parent(q)) == f(q))
333  parent(p) = parent(q);
334  s.append(p);
335 
336  mln_assertion((q = parent(p)) == parent(q) || fext(q) != fext(parent(q)));
337  }
338  }
339  std::cout << "Canonization: " << tm << " s" << std::endl;
340 
341  //mln_postcondition(internal::compute_parent_postconditions(fext, s, parent));
342 
343  tree::data<I, p_array<mln_psite(I)> > tree(fext, parent, s);
344  trace::exiting("morpho::tree::impl::generic::dual_union_find");
345 
346  return tree;
347  }
348 
349  } // end of namespace mln::morpho::tree::impl::generic
350 
351  } // end of namespace mln::morpho::tree::impl
352 
353 # endif // ! MLN_INCLUDE_ONLY
354 
355  } // end of namespace mln::morpho::tree
356 
357  } // end of namespace mln::morpho
358 
359 } // end of namespace mln
360 
361 #endif // !MLN_MORPHO_TREE_IMLP_DUAL_UNION_FIND_HH