rpc_maxtree.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, Inc., 51 Franklin Street, Fifth Floor,
00016 // 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_RPC_MAXTREE_HH
00029 # define OLENA_LRDE_UFMT_RPC_MAXTREE_HH
00030 
00031 # include <oln/lrde/ufmt/utils.hh>
00032 # include <oln/lrde/ufmt/ap_maxtree.hh>
00033 
00034 # include <vector>
00035 
00036 
00037 namespace oln
00038 {
00039 
00040   namespace lrde
00041   {
00042 
00043     namespace ufmt
00044     {
00045 
00046 
00047       // FIXME: doc.
00048 
00049       template <class I>
00050       struct rpc_maxtree : public ap_maxtree<I>
00051       {
00052         typedef ap_maxtree<I> super;
00053         using super::f;
00054         using super::nbh;
00055         using super::par;
00056         oln_lrde_ufmt_import_ap_maxtree_typedefs;
00057 
00058         unsigned nnodes;
00059 
00060         // aux data
00061         std::vector<dpoint> dp;
00062         unsigned nb;
00063 
00064 
00065         // ctor
00066 
00067         rpc_maxtree(const abstract::image<I>& f,
00068                     const oln_neighborhood_type(I)& nbh)
00069           :
00070           super(f, nbh)
00071         {
00072         }
00073 
00074         void go()
00075         {
00076           init();
00077           compute_parent();  // 1st pass
00078           extract_maxtree(); // 2nd pass
00079         }
00080 
00081         void init()
00082         {
00083           nb = pre<I>(nbh, dp);
00084           nnodes = 0;
00085         }
00086 
00087         void compute_parent()
00088         {
00089           oln_iter_type(I) p(f);
00090           for_all(p)
00091             {
00092               make_set(p); // FIXME: is it useful?
00093               point n = p + dp[0];
00094               if (f.hold(n))
00095                 insert(n, p); // FIXME: is it useful to distinguish insert from update?
00096               for (unsigned i = 1; i < nb; ++i)
00097                 {
00098                   n = p + dp[i];
00099                   if (f.hold(n))
00100                     if (f[p] >= f[n])
00101                       update(p, n);
00102                     else
00103                       update(n, p);
00104                 }
00105             }
00106         }
00107 
00108         void extract_maxtree()
00109         {
00110           // FIXME: TODO
00111         }
00112 
00113         void insert(const point& n, const point& p)
00114         {
00115           point r = anc(n, f[p]);
00116           
00117           if (f[p] != f[r])
00118             ++nnodes;
00119 
00120           if (f[r] <= f[p])
00121             par[p] = r;
00122           else
00123             {
00124               if (par[r] != r) // split
00125                 par[p] = par[r];
00126               par[r] = p;
00127             }
00128         }
00129 
00130 
00131         void update(point x, point y)
00132         {
00133           assert(x != y); // invariant
00134           assert(f[x] >= f[y]); // invariant
00135 
00136           point a = anc(x, f[y]);
00137           point b = find_level_root(y);
00138 
00139           assert(f[x] >= f[a] and f[a] >= f[y] and f[y] == f[b]); // invariant
00140 
00141           if (a == b)
00142             return; // already merged
00143 
00144           if (f[b] != f[a])
00145             ++nnodes;
00146 
00147           point memo = par[b];
00148 
00149           if (f[b] == f[a])
00150             par[b] = a; // simple plug
00151           else
00152             {
00153               if (par[a] != a)
00154                 par[b] = par[a];
00155               par[a] = b;
00156             }
00157 
00158           assert(f[memo] <= f[a]); // invariant
00159           update(a, memo);
00160 
00161           // FIXME: this algo looks ok and seems to work (...?)
00162           // it is very close to the 'insert' algo running with
00163           // "insert(x, find_level_root(y))" after the "if..swap"
00164           // FIXME: so it can be bettered...
00165         }
00166 
00167 
00168 
00169         void update__primary_version(point x, point y)
00170         {
00171           assert(x != y); // invariant
00172 
00173           if (f[x] < f[y])
00174             swap(x, y);
00175           assert(f[x] >= f[y]); // invariant
00176 
00177           point xx = anc(x, f[y]);
00178           assert(f[xx] >= f[y]);
00179 
00180           point yy = anc(y, f[y]);
00181           assert(yy == find_level_root(y));
00182           assert(f[yy] == f[y]);
00183 
00184           assert(f[yy] <= f[xx]);
00185           // if (f[yy] < f[xx]) std::cout << '<'; else std::cout << '=';
00186 
00187 
00188           if (xx == yy)
00189             return; // already merged
00190 
00191           point memo = par[yy];
00192 
00193           if (f[xx] == f[yy])
00194             {
00195               par[yy] = xx; // simple plug => 2 nodes merge
00196               update(xx, memo);
00197             }
00198           else
00199             {
00200               assert(f[yy] < f[xx]);
00201               if (par[xx] == xx)
00202                 {
00203                   par[xx] = yy; // new tree root
00204                   // FIXME: the end?
00205                 }
00206               else
00207                 {
00208                   // insertion
00209                   point bot = par[xx];
00210                   par[xx] = yy;
00211                   par[yy] = bot;
00212                   update(xx, memo);
00213                 }
00214             }
00215 
00216           // FIXME: this algo looks ok and seems to work (...?)
00217           // it is very close to the 'insert' algo running with
00218           // "insert(x, find_level_root(y))" after the "if..swap"
00219           // FIXME: so it can be bettered...
00220         }
00221 
00222 
00223 
00224         void insert__unfold_version(const point& n, const point& p)
00225         {
00226           if (f[n] <= f[p])
00227             {
00228               // nota bene: "point r = anc(n, f[p]);" leads to "r == n" in that case
00229               par[p] = n;
00230               // new (temporary?) regional maximum
00231             }
00232           else
00233             // f[n] > f[p]
00234             {
00235               point r = anc(n, f[p]);
00236               assert(f[r] >= f[p]);
00237               if (f[r] == f[p])
00238                 {
00239                   par[p] = r; // p is plugged into this node/component
00240                 }
00241               else
00242                 {
00243                   if (par[r] == r) // tree root
00244                     par[r] = p;
00245                   else
00246                     // insertion between a couple of nodes linked together
00247                     // 2 new links are created
00248                     {
00249                       point bot = par[r];
00250                       par[r] = p;
00251                       par[p] = bot;
00252                     }
00253                 }
00254             }
00255         }
00256 
00257 
00258       }; // end of class rpc_maxtree
00259 
00260 
00261 
00262     } // end of namespace oln::lrde::ufmt
00263 
00264   } // end of namespace oln::lrde
00265 
00266 } // end of namespace oln
00267 
00268 
00269 #endif // ! OLENA_LRDE_UFMT_RPC_MAXTREE_HH

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