Biorithm  1.1
 All Classes Functions Variables Typedefs Friends
ItemSetTree.h
00001 /**************************************************************************
00002  * Copyright (c) 2007 Clifford Conley Owens III                           *
00003  *                                                                        *
00004  * This file is part of Biorithm.                                         *
00005  *                                                                        *
00006  * Biorithm is free software: you can redistribute it and/or modify       *
00007  * it under the terms of the GNU General Public License as published by   *
00008  * the Free Software Foundation, either version 3 of the License, or      *
00009  * (at your option) any later version.                                    *
00010  *                                                                        *
00011  * Biorithm is distributed in the hope that it will be useful,            *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
00014  * GNU General Public License for more details.                           *
00015  *                                                                        *
00016  * You should have received a copy of the GNU General Public License      *
00017  * along with Biorithm.  If not, see <http://www.gnu.org/licenses/>.      *
00018  *                                                                        *
00019  **************************************************************************/
00020 
00032 #ifndef ITEMSETTREE_H
00033 #define ITEMSETTREE_H
00034 
00035 #define SIZE_BYTE 8
00036 
00037 // ---------------------------- Internal Headers ---------------------------- //
00038 
00039 #include "ItemSet.h"
00040 
00046 template <typename t> class ItemSetTree
00047 {
00048     public:
00049         struct node
00050         {
00051             struct node* parent;
00052             vector<struct node*> derivs;
00053             t val;
00054         };
00055     
00056     private:
00057         // The set of items
00058         struct node root;
00059 
00060         // The number of different items
00061         unsigned int max;
00062 
00063         // The total size
00064         unsigned int tsize;
00065 
00066         // The livel sizes
00067         vector<unsigned int> lsizes;
00068 
00069         // The last position
00070         struct node* lastpos;
00071 
00072         // The itemset representing the last position
00073         ItemSet lastis;
00074 
00075         // Helper methods
00076         void copy(struct node* target, const struct node* subroot)
00077         {
00078             target->val = subroot->val;
00079             for (unsigned int i = 0; i < subroot->derivs.size(); i++)
00080             {
00081                 if (subroot->derivs[i])
00082                 {
00083                     target->derivs[i] = new struct node;
00084                     target->derivs[i]->parent = target->derivs[i];
00085                     target->derivs[i]->derivs.resize(
00086                         subroot->derivs[i]->derivs.size(), NULL);
00087                     copy(target->derivs[i], subroot->derivs[i]);
00088                 }
00089             }
00090         }
00091 
00092         void clearHelper(struct node* subroot)
00093         {
00094             // Go through all the potential children of the subroot 
00095             for (unsigned int i = 0; i < subroot->derivs.size(); i++)
00096             {
00097                 if (subroot->derivs[i])
00098                 {
00099                     clearHelper(subroot->derivs[i]);
00100                     delete subroot->derivs[i];
00101                 }
00102             }
00103         }
00104 
00105 
00106     public:
00107         class ConstIterator;
00108 
00109         // The iterator class
00110         class Iterator
00111         {
00112             private:
00113                 struct node* pos;
00114                 ItemSet is;
00115                 unsigned int max;
00116 
00117             public:
00118                 Iterator(struct node* pos = NULL, unsigned int max = 0)
00119                 {
00120                     this->pos = pos;
00121                     this->max = max;
00122                 }
00123 
00124                 Iterator(const Iterator& src)
00125                 {
00126                     *this = src;
00127                 }
00128 
00129                 ~Iterator()
00130                 {
00131 
00132                 }
00133 
00134                 Iterator& operator =(const Iterator& rhs)
00135                 {
00136                     pos = rhs.pos;
00137                     is = rhs.is;
00138                     max = rhs.max;
00139                 }
00140 
00141                 bool operator ==(const Iterator& rhs) const
00142                 {
00143                     return pos == rhs.pos;
00144                 }
00145 
00146                 bool operator !=(const Iterator& rhs) const
00147                 {
00148                     return pos != rhs.pos;
00149                 }
00150 
00151                 t& operator *() const
00152                 {
00153                     return pos->val;
00154                 }
00155 
00156                 void advance_down()
00157                 {
00158                     // Make sure we aren't already at the end
00159                     if (pos == NULL)
00160                     {
00161                         return;
00162                     }
00163 
00164                     int lastindex = (int)is.size() - 1;
00165                     int pitem;
00166                     if (lastindex == -1)
00167                     {
00168                         pitem = -1;
00169                     }
00170                     else
00171                     {
00172                         pitem = is[lastindex];
00173                     }
00174                     for (unsigned int i = 0; i < (max - pitem) - 1; i++)
00175                     {
00176                         if (pos->derivs[i])
00177                         {
00178                             advance_down(i + pitem + 1);
00179                             return;
00180                         }
00181                     }
00182                     pos = NULL;
00183                 }
00184 
00185                 void advance_down(unsigned int item)
00186                 {
00187                     // Make sure we aren't already at the end
00188                     if (pos == NULL)
00189                     {
00190                         return;
00191                     }
00192 
00193                     int lastindex = is.size() - 1;
00194                     int pitem;
00195                     if (lastindex == -1)
00196                     {
00197                         pitem = -1;
00198                     }
00199                     else
00200                     {
00201                         pitem = is[lastindex];
00202                     }
00203                     if (pos->derivs[(item - pitem) - 1])
00204                     {
00205                         pos = pos->derivs[(item - pitem) - 1];
00206                         is.insert(item);
00207                         return;
00208                     }
00209                     pos = NULL;
00210                 }
00211 
00212                 void setval(const t& val)
00213                 {
00214                     pos->val = val;
00215                 }
00216 
00217                 const ItemSet& itemset() const
00218                 {
00219                     return is;
00220                 }
00221 
00222                 friend class ConstIterator;
00223         };
00224 
00225         // The const iterator class
00226         class ConstIterator
00227         {
00228             private:
00229                 const struct node* pos;
00230                 ItemSet is;
00231                 unsigned int max;
00232 
00233             public:
00234                 ConstIterator(const struct node* pos = NULL,
00235                     unsigned int max = 0)
00236                 {
00237                     this->pos = pos;
00238                     this->max = max;
00239                 }
00240 
00241                 ConstIterator(const ConstIterator& src)
00242                 {
00243                     *this = src;
00244                 }
00245 
00246                 ~ConstIterator()
00247                 {
00248 
00249                 }
00250 
00251                 ConstIterator(const Iterator& src)
00252                 {
00253                     *this = src;
00254                 }
00255 
00256                 ConstIterator& operator =(const ConstIterator& rhs)
00257                 {
00258                     pos = rhs.pos;
00259                     is = rhs.is;
00260                     max = rhs.max;
00261                 }
00262 
00263                 ConstIterator& operator =(const Iterator& rhs)
00264                 {
00265                     pos = rhs.pos;
00266                     is = rhs.is;
00267                     max = rhs.max;
00268                 }
00269 
00270                 bool operator ==(const ConstIterator& rhs) const
00271                 {
00272                     return pos == rhs.pos;
00273                 }
00274 
00275                 bool operator !=(const ConstIterator& rhs) const
00276                 {
00277                     return pos != rhs.pos;
00278                 }
00279 
00280                 const t& operator *() const
00281                 {
00282                     return pos->val;
00283                 }
00284 
00285                 void advance_up()
00286                 {
00287                     // Make sure we aren't already at the end
00288                     if (pos == NULL)
00289                     {
00290                         return;
00291                     }
00292 
00293                     if (!is.empty()) 
00294                     {
00295                         is.remove();
00296                     }
00297                     pos = pos->parent;
00298                 }
00299 
00300                 void advance_down()
00301                 {
00302                     // Make sure we aren't already at the end
00303                     if (pos == NULL)
00304                     {
00305                         return;
00306                     }
00307 
00308                     int lastindex = (int)is.size() - 1;
00309                     int pitem;
00310                     if (lastindex == -1)
00311                     {
00312                         pitem = -1;
00313                     }
00314                     else
00315                     {
00316                         pitem = is[lastindex];
00317                     }
00318                     for (unsigned int i = 0; i < (max - pitem) - 1; i++)
00319                     {
00320                         if (pos->derivs[i])
00321                         {
00322                             advance_down(i + pitem + 1);
00323                             return;
00324                         }
00325                     }
00326                     pos = NULL;
00327                 }
00328 
00329                 void advance_down(unsigned int item)
00330                 {
00331                     // Make sure we aren't already at the end
00332                     if (pos == NULL)
00333                     {
00334                         return;
00335                     }
00336 
00337                     int lastindex = is.size() - 1;
00338                     int pitem;
00339                     if (lastindex == -1)
00340                     {
00341                         pitem = -1;
00342                     }
00343                     else
00344                     {
00345                         pitem = is[lastindex];
00346                     }
00347                     if (pos->derivs[(item - pitem) - 1])
00348                     {
00349                         pos = pos->derivs[(item - pitem) - 1];
00350                         is.insert(item);
00351                         return;
00352                     }
00353                     pos = NULL;
00354                 }
00355 
00356                 void advance_rightp()
00357                 {
00358                     // Make sure we aren't already at the end
00359                     if (pos == NULL)
00360                     {
00361                         return;
00362                     }
00363 
00364                     // No move to the right keeping the same parent
00365                     int lastindex = is.size() - 1;
00366                     if (lastindex == -1)
00367                     {
00368                         pos = NULL;
00369                         return;
00370                     }
00371                     unsigned int curitem = is[lastindex];
00372                     int pitem;
00373                     if (!lastindex)
00374                     {
00375                         pitem = -1;
00376                     }
00377                     else
00378                     {
00379                         pitem = is[lastindex - 1];
00380                     }
00381                     advance_up();
00382                     for (unsigned int i = curitem - pitem;
00383                         i < (max - pitem) - 1; i++)
00384                     {
00385                         if (pos->derivs[i])
00386                         {
00387                             advance_down(pitem + i + 1);
00388                             return;
00389                         }
00390                     }
00391                     pos = NULL;
00392                 }
00393 
00394                 void advance_right()
00395                 {
00396                     // Make sure we aren't already at the end
00397                     if (pos == NULL)
00398                     {
00399                         return;
00400                     }
00401 
00402                     // First let's just see if we can move right with respect
00403                     // to a parent
00404                     ConstIterator iterbu = *this;
00405                     advance_rightp();
00406                     if (pos != NULL)
00407                     {
00408                         return;
00409                     }
00410 
00411                     // We must move upward, so let's start over
00412                     *this = iterbu;
00413                     advance_up();
00414                     advance_right();
00415                     iterbu = *this;
00416                     advance_down();
00417                     while (!pos)
00418                     {
00419                         *this = iterbu;
00420                         advance_right();
00421                         if (!pos)
00422                         {
00423                             return;
00424                         }
00425                         iterbu = *this;
00426                         advance_down();
00427                     }
00428                 }
00429 
00430                 const ItemSet& itemset() const
00431                 {
00432                     return is;
00433                 }
00434         };
00435 
00436         ItemSetTree(unsigned int max = 0)
00437         {
00438             this->max = max;
00439             root.derivs.resize(max, NULL);
00440             root.parent = NULL;
00441             tsize = 1;
00442             lsizes.push_back(1);
00443             lastpos = &root;
00444         }
00445 
00446         ItemSetTree(const ItemSetTree& src)
00447         {
00448             *this = src;
00449         }
00450 
00451         ~ItemSetTree()
00452         {
00453             clear();
00454         }
00455 
00456         ItemSetTree& operator =(const ItemSetTree& rhs)
00457         {
00458             clear();
00459             max = rhs.max;
00460             tsize = rhs.tsize;
00461             lsizes = rhs.lsizes;
00462             root.derivs.resize(max, NULL);
00463             copy(&root, &rhs.root);
00464             // lastpos broken on copy
00465             lastpos = &root;
00466             return *this;
00467         }
00468 
00469         void clear()
00470         {
00471             clearHelper(&root);
00472             for (unsigned int i = 0; i < max; i++)
00473             {
00474                 root.derivs[i] = NULL;
00475             }
00476         }
00477 
00478         Iterator end()
00479         {
00480             return Iterator(NULL, max);
00481         }
00482 
00483         ConstIterator end() const
00484         {
00485             return ConstIterator(NULL, max);
00486         }
00487 
00488     private:
00489 
00490         Iterator begin_down(const Iterator& iter, unsigned int level)
00491         {
00492             if (!level)
00493             {
00494                 return iter;
00495             }
00496 
00497             Iterator c = end();
00498             int start;
00499             if (iter.itemset().empty())
00500             {
00501                 start = 0;
00502             }
00503             else
00504             {
00505                 start = iter.itemset().back() + 1;
00506             }
00507             for (unsigned int i = start; i < max && c == end(); i++)
00508             {
00509                 c = iter;
00510                 c.advance_down(i);
00511                 if (c != end())
00512                 {
00513                     c = begin_down(c, level - 1);
00514                 }
00515             }
00516             return c;
00517         }
00518 
00519     public:
00520 
00521         Iterator begin()
00522         {
00523             return Iterator(&root, max);
00524         }
00525 
00526         ConstIterator begin() const
00527         {
00528             return ConstIterator(&root, max);
00529         }
00530 
00531         Iterator begin(unsigned int level)
00532         {
00533             return begin_down(begin(), level);
00534         }
00535 
00536         ConstIterator begin(unsigned int level) const
00537         {
00538             return begin_down(begin(), level);
00539         }
00540 
00541         Iterator find(const ItemSet& is)
00542         {
00543             Iterator iter = begin();
00544             for (unsigned int i = 0; i < is.size() && iter != end(); i++)
00545             {
00546                 iter.advance_down(is[i]);
00547             }
00548             return iter;
00549         }
00550 
00551         ConstIterator find(const ItemSet& is) const
00552         {
00553             ConstIterator iter = begin();
00554             for (unsigned int i = 0; i < is.size() && iter != end(); i++)
00555             {
00556                 iter.advance_down(is[i]);
00557             }
00558             return iter;
00559         }
00560 
00561         unsigned int size() const
00562         {
00563             return tsize;
00564         }
00565 
00566         unsigned int size(unsigned int level) const
00567         {
00568             if (level < lsizes.size()) 
00569             {
00570                 return lsizes[level];
00571             }
00572             return 0;
00573         }
00574 
00575         bool empty() const
00576         {
00577             return !tsize;
00578         }
00579 
00580         bool empty(unsigned int level) const
00581         {
00582             return !size(level);
00583         }
00584 
00585         void insert(const ItemSet& is, const t& val)
00586         {
00587             // Broken if we have not built the tree up
00588             struct node* pos = &root;
00589             int previtem = -1;
00590             int lastindex = is.size() - 1;
00591             for (int i = 0; pos && i < lastindex; i++)
00592             {
00593                 pos = pos->derivs[(is[i] - previtem) - 1];
00594                 previtem = is[i];
00595             }
00596             unsigned int lastitem = (is[lastindex] - previtem) - 1;
00597             pos->derivs[lastitem] = new struct node;
00598             pos->derivs[lastitem]->parent = pos;
00599             pos->derivs[lastitem]->val = val;
00600             pos->derivs[lastitem]->derivs.resize((max - is.back()) - 1, NULL);
00601             lastpos = pos->derivs[lastitem];
00602             lastis = is;
00603             if (lsizes.size() <= is.size())
00604             {
00605                 lsizes.resize(is.size() + 1, 0);
00606             }
00607             lsizes[is.size()]++;
00608             tsize++;
00609         }
00610 
00611         void remove()
00612         {
00613             struct node* temppos = lastpos->parent;
00614             int pitem;
00615             if (lastis.size() < 2)
00616             {
00617                 pitem = -1;
00618             }
00619             else
00620             {
00621                 pitem = lastis[lastis.size() - 2];
00622             }
00623             temppos->derivs[(lastis.back() - pitem) - 1] = NULL;
00624             delete lastpos;
00625             lastpos = temppos;
00626             lsizes[lastis.size()]--;
00627             tsize--;
00628             lastis.remove();
00629         }
00630 
00631         void setval(const t& val) const
00632         {
00633             lastpos->val = val;
00634         }
00635 
00636         t& getval() const
00637         {
00638             return lastpos->val;
00639         }
00640 };
00641 
00642 #endif
 All Classes Functions Variables Typedefs Friends