generic_salembier.hh

00001 // Copyright (C) 2006  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, 51 Franklin Street, Fifth Floor,
00016 // Boston, Boston, MA 02110-1301, 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_LRDE_UFMT_GENERIC_SALEMBIER_HH
00029 # define OLENA_LRDE_UFMT_GENERIC_SALEMBIER_HH
00030 
00031 
00032 # include <climits> // For INT_MAX.
00033 # include <cfloat> // For FLT_MAX.
00034 # include <queue>
00035 # include <set>
00036 # include <map>
00037 
00038 # include <oln/level/fill.hh>
00039 # include <oln/lrde/ufmt/utils.hh>
00040 
00041 
00042 
00043 namespace oln
00044 {
00045 
00046   namespace lrde
00047   {
00048 
00049     namespace ufmt
00050     {
00051 
00052       template <class V, class P>
00053       struct generic_hqueue_t
00054       {
00055         typedef std::map<V, std::queue<P> > multi_queue_t;
00056 
00057         void add(const V& h, const P& p)
00058         {
00059           q[h].push(p);
00060         }
00061 
00062         // Add an empty queue a level H, if there is none.
00063         void init(const V& h)
00064         {
00065           q.insert(std::make_pair(h, std::queue<P>()));
00066         }
00067 
00068         bool empty(const V& h) const
00069         { 
00070           typename multi_queue_t::const_iterator i = q.find(h);
00071           if (i == q.end())
00072             return true;
00073           else
00074             return i->second.empty();
00075         }
00076 
00077         P first(const V& h)
00078         {
00079           assertion (not empty(h));
00080 
00081           P tmp = q[h].front();
00082           q[h].pop();
00083           return tmp;
00084         }
00085         
00086         unsigned size() const
00087         {
00088           unsigned s = 0;
00089           for (typename multi_queue_t::const_iterator i = q.begin();
00090                i != q.end(); ++i)
00091             s += i->second.size();
00092           return s;
00093         }
00094 
00095         void print (std::ostream& os)
00096         {
00097           os << "hqueue = {";
00098           for (typename multi_queue_t::const_iterator i = q.begin();
00099                i != q.end(); ++i)
00100             if (not i->second.empty())
00101               {
00102                 os << "  " << i->first << " -> { ";
00103                 std::queue<P> queue_copy = i->second;
00104                 while (not queue_copy.empty())
00105                   {
00106                     os << queue_copy.front () << " ";
00107                     queue_copy.pop();
00108                   }
00109                 os << "}";
00110               }
00111           os << " }" << std::endl;
00112         }
00113 
00114         multi_queue_t q;
00115       };
00116 
00117 
00118       template < class I,
00119                  class Greater = std::greater< oln_value_type(I) > >
00120       struct generic_salembier
00121       {
00122         typedef oln_point_type(I) point;
00123         typedef oln_value_type(I) value;
00124         typedef oln_neighborhood_type(I) Nbh;
00125         typedef oln_iter_type(Nbh) niter;
00126 
00127         enum {
00128           not_analyzed = INT_MAX - 2,
00129           in_the_queue = INT_MAX - 1
00130         };
00131 
00132         const I& f;
00133         const Nbh& nbh;
00134 
00135         typename mute<I, int>::ret status;
00136 
00137         typedef std::map<value, unsigned> number_nodes_t;
00138         number_nodes_t number_nodes;
00139         typedef std::set<value> node_at_level_t;
00140         node_at_level_t node_at_level;
00141         generic_hqueue_t<value, point> hqueue;
00142         value h_min;
00143 
00144         typedef std::set< value, Greater > levels_t;
00145         typedef typename levels_t::const_iterator level_iterator;
00146         // Set of all values present in the input image, sorting in
00147         // descending order.
00148         levels_t levels;
00149 
00150         // Level comparison function.
00151         Greater level_greater;
00152 
00153         typedef std::pair<unsigned, value> pair_t;
00154         std::map<pair_t, pair_t> father;
00155 
00156 # ifdef OLN_DEBUG
00157         unsigned npoints;
00158 # endif // OLN_DEBUG
00159 
00160         generic_salembier(const abstract::image<I>& f,
00161                           const oln_neighborhood_type(I)& nbh) :
00162           f(f.exact()),
00163           nbh(nbh),
00164           // FIXME: status should NOT be initialized here!
00165           // (but in "init()") (??)
00166           status(f.size())
00167 # ifdef OLN_DEBUG
00168           , npoints(f.npoints())
00169 # endif // OLN_DEBUG
00170         {
00171         }
00172 
00173 
00174         void go()
00175         {
00176           init();
00177           flood(h_min);
00178         }
00179 
00180 
00181         void init()
00182         {
00183           level::fill(status, not_analyzed);
00184 
00185           oln_iter_type(I) p(f);
00186           p = mlc::begin;
00187           point p_min = p;
00188           h_min = f[p];
00189           for_all(p)
00190             {
00191               // Init levels.
00192               levels.insert(f[p]);
00193               // Find the global minimum.
00194               if (level_greater(h_min, f[p])) // Was: f[p] < h_min
00195                 {
00196                   h_min = f[p];
00197                   p_min = p;
00198                 }
00199             }
00200           hqueue.add(h_min, p_min);
00201         }
00202 
00203 
00204 # ifdef OLN_DEBUG
00205         void update_status (std::ostream& ostr)
00206         {
00207           static unsigned nupdates = 0;
00208           static const unsigned step = 1;
00209           static unsigned next_step = step;
00210           ++nupdates;
00211           unsigned percent = nupdates * 100 / npoints;
00212           if (percent >= next_step)
00213             {
00214               // Print.
00215               std::cerr << percent << "% points processed" << std::endl;
00216               // Increase the next step.
00217               while (percent >= next_step)
00218                 next_step += step;
00219             }
00220         }
00221 # endif // OLN_DEBUG
00222         
00223         level_iterator flood(const value& h)
00224         {
00225           level_iterator m;
00226           while (not hqueue.empty(h))
00227             {
00228               point p = hqueue.first(h);
00229 
00230               status[p] = get(number_nodes, h, 0u);
00231 # ifdef OLN_DEBUG
00232               update_status(std::cerr);
00233 # endif // OLN_DEBUG
00234 
00235               oln_neighb_type(Nbh) q(nbh, p);
00236               for_all(q)
00237                 {
00238                 if (f.hold(q))
00239                   {
00240                     if (status[q] == not_analyzed)
00241                       {
00242                         hqueue.add(f[q], q);
00243                         status[q] = in_the_queue;
00244                         node_at_level.insert(f[q]); // err. 1
00245                         if (f[q] > f[p])
00246                           {
00247                             m = levels.find(f[q]);
00248                             if (m == levels.end())
00249                               abort();
00250                             while (m != levels.end() and *m > h) // err. 2
00251                               m = flood(*m);
00252                           }
00253                       }
00254                   }
00255                 }
00256             }
00257           number_nodes[h] = get(number_nodes, h, 0u) + 1;
00258 
00259           // Let *m be the greatest level lower than h.
00260           m = levels.find(h);
00261           if (m == levels.end())
00262             abort();
00263           ++m;                                  // Was: « m = h - 1 ».
00264           while (m != levels.end() and          // Was: « m >= 0 ».
00265                  node_at_level.find(*m) == node_at_level.end())
00266             ++m;                                // Was: « m = h - 1 ».
00267           int i = get(number_nodes, h, 0u) - 1; // Was:
00268                                                 // « i = number_nodes[h] - 1 ».
00269           if (m != levels.end())                // Was: « m >= 0 ».
00270             {
00271               int j = get(number_nodes, *m, 0u);
00272               father[pair_t(i, h)] = pair_t(j, *m);
00273             }
00274           else
00275             {
00276               father[pair_t(i, h)] = pair_t(i, h);
00277             }
00278           node_at_level.erase(h);
00279           return m;
00280         }
00281 
00282 
00283         unsigned n_level_roots() const
00284         {
00285           return father.size();
00286         }
00287 
00290         template <typename Key, typename Data,
00291                   typename Compare, typename Alloc>
00292         Data get(const std::map<Key, Data, Compare, Alloc>& map,
00293                  const Key& key, const Data& default_val) const
00294         {
00295           typename std::map<Key, Data, Compare, Alloc>::const_iterator n =
00296             map.find(key);
00297           if (n != map.end())
00298             return n->second;
00299           else
00300             return default_val;
00301         }
00302 
00303       }; // end of struct generic_salembier
00304 
00305 
00306     } // end of namespace oln::lrde::ufmt
00307 
00308   } // end of namespace oln::lrde
00309 
00310 } // end of namespace oln
00311 
00312 
00313 #endif // ! OLENA_LRDE_UFMT_GENERIC_SALEMBIER_HH

Generated on Tue Feb 20 20:19:43 2007 for Olena by  doxygen 1.5.1