attribute_union_find.hh

00001 // Copyright (C) 2001, 2002, 2003, 2004  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef OLENA_ATTRIBUTE_UNION_FIND_HH
00029 # define OLENA_ATTRIBUTE_UNION_FIND_HH
00030 
00031 #include <oln/level/fill.hh>
00032 
00033 #include <ntg/bin.hh>
00034 
00035 #include <vector>
00036 #include <oln/utils/histogram.hh>
00037 #include <oln/morpho/attributes.hh>
00038 
00039 namespace oln {
00040   namespace morpho {
00041     namespace fast {
00042       namespace tarjan {
00043 
00055         template<class T, class ATTRIBUTE, class Env = attr_env_type(ATTRIBUTE)>
00056         struct tarjan_set
00057         {
00058           typedef oln_point_type(T)                     point_type; 
00059           typedef oln_value_type(T)                     data_type; 
00060           typedef oln_concrete_type(T)                  image_type; 
00061           typedef typename ATTRIBUTE::lambda_type       lambda_type; 
00062           typedef Env                                   env_type; 
00063 
00069           tarjan_set(const image_type& ima, const env_type &env) : input_(ima),
00070                                                                    parent_(ima.size()),
00071                                                                    aux_data_(ima.size()),
00072                                                                    env_(env)
00073           {
00074             level::fill(parent_, INACTIVE());
00075           }
00076 
00085           template<bool closing, class N>
00086           image_type
00087           get_comptute(const lambda_type & lambda,
00088                        const abstract::neighborhood<N>& Ng)
00089           {
00090             lambda_ = &lambda;
00091 
00092             std::vector<point_type>     I(input_.npoints());
00093 
00094             oln::utils::select_distrib_sort<closing>()(input_, I);
00095 
00096             level::fill(aux_data_, ntg_sup_val(lambda_type));
00097             aux_data_.border_adapt_assign(Ng.delta(), ntg_sup_val(lambda_type));
00098 
00099             // We are ready to perform stuff
00100             for (unsigned int p = 0; p < I.size(); ++p)
00101               {
00102                 point_type p_p = I[p];
00103                 make_set(p_p);
00104                 oln_neighb_type(N) Q_prime(Ng, p_p);
00105                 for_all (Q_prime)
00106                   if (is_proc(Q_prime))
00107                     uni(Q_prime.cur(), p_p);
00108               }
00109 
00110             // Resolving phase
00111             image_type output(input_.size());
00112             for (int p = I.size() - 1; p >= 0; --p)
00113               {
00114                 point_type p_p = I[p];
00115                 if ((parent_[p_p] == ACTIVE()) ||  (parent_[p_p] == INACTIVE()))
00116                   output[p_p] = input_[p_p];
00117                 else
00118                   output[p_p] = output[parent_[p_p]];
00119                 // this code is equivalent to
00120                 //      output[I[p].first] = input_[find_root(I[p].first)];
00121 
00122               }
00123             return output;
00124           }
00125 
00126         protected:
00130           static const point_type&
00131           ACTIVE()
00132           {
00133             static struct foo_def
00134             {
00135               point_type elt;
00136               foo_def()
00137               {
00138                 const unsigned dim = point_type::dim;
00139                 for (unsigned i = 0; i < dim; ++i )
00140                   elt.nth(i) = -1;
00141               }
00142             } tmp;
00143 
00144             return tmp.elt;
00145           }
00146 
00150           static const point_type&
00151           INACTIVE()
00152           {
00153             static struct foo_def
00154             {
00155               point_type elt;
00156               foo_def() {
00157                 const unsigned dim = point_type::dim;
00158                 for (unsigned i = 0; i < dim; ++i )
00159                   elt.nth(i) = -2;
00160               }
00161             } tmp;
00162 
00163             return tmp.elt;
00164           }
00165 
00170           void
00171           make_set(const point_type& x)
00172           {
00173             precondition(parent_[x] == INACTIVE());
00174             parent_[x] = ACTIVE();
00175             aux_data_[x] = ATTRIBUTE(input_, x, env_);
00176           }
00177 
00182           point_type
00183           find_root(const point_type& x)
00184           {
00185             if ((parent_[x] != ACTIVE()) && (parent_[x] != INACTIVE()))
00186               {
00187                 parent_[x] = find_root(parent_[x]);
00188                 return parent_[x];
00189               }
00190             else
00191               return x;
00192           }
00193 
00199           bool
00200           criterion(const point_type& x, const point_type& y)
00201           {
00202             precondition((parent_[x] == ACTIVE()) || (parent_[x] == INACTIVE()));
00203             precondition((parent_[y] == ACTIVE()) || (parent_[y] == INACTIVE()));
00204             return ( (input_[x] == input_[y]) || (aux_data_[x] < *lambda_));
00205           }
00206 
00212           void
00213           uni(const point_type& n, const point_type& p)
00214           {
00215             point_type r = find_root(n);
00216             if (r != p)
00217               if (criterion(r,p))
00218                 {
00219                   aux_data_[p] += aux_data_[r];
00220                   parent_[r] = p;
00221                 }
00222               else
00223                 {
00224                   aux_data_[p] = *lambda_;
00225                 }
00226           }
00227 
00231           bool is_proc(const point_type &p) const
00232           {
00233             //FIXME: odd way to call !=,  but it is to help the compiler
00234             //to find the good one  when ATTRIBUTE is templeted by types
00235             //in other namespaces.
00236 
00237             // return aux_data_[p] != ntg_max_val(lambda_type);
00238             return aux_data_[p].operator!=(ntg_sup_val(lambda_type));
00239           };
00240 
00241 
00242           const image_type                      &input_; 
00243           typename mute<T, point_type>::ret     parent_; 
00244           typename mute<T, ATTRIBUTE>::ret      aux_data_; 
00245           const lambda_type                     *lambda_; 
00246           const env_type                        env_; 
00247         };
00248       } // !tarjan
00249     } // !fast
00250   } // !morph
00251 } // !oln
00252 #endif

Generated on Thu Apr 15 20:13:05 2004 for Olena by doxygen 1.3.6-20040222