00001
00009 #include "common.hpp"
00010 #include "common/log.h"
00011 #include "io/input/transaction_reader/TransactionReader.hpp"
00012 #include "fpgrowth/buildfptree.hpp"
00013
00014
00015 namespace bracz {
00016
00018 typedef struct node_t {
00019 node_t *parent;
00020 item_t item;
00021 counter_t counter;
00022 node_t *headerlink;
00023 } node_t;
00024
00025
00034 template<class INPUT,class BUILDTREE, FirstLevel FIRSTLEVEL, bool TD, bool SINGLE> class ClassicFPStructure {
00035 private:
00036
00037 public:
00039 typedef struct fptree_t {
00040 counter_t *freqs;
00041 node_t **headertable;
00042 counter_t rootfreq;
00043 counter_t DINLINE getFrequency(item_t i) {
00044 return freqs[i];
00045 }
00046
00047 counter_t DINLINE getRootFrequency() {
00048 return rootfreq;
00049 }
00050 } fptree_t;
00051
00052
00053 counter_t getTransactionCount() {
00054 return transaction_count;
00055 }
00056
00057 private:
00058
00060 INPUT *inp;
00061
00062 protected:
00063
00064 fptree_t fulltree;
00065
00066 std::vector<fptree_t> l1trees;
00067
00068
00069 counter_t transaction_count;
00070
00072 singleualloc<node_t, 10*1024> nodeallocator;
00074 singlesalloc<fptree_t,100> treealloc;
00075
00076
00078 blockstack<stackmultiblock<node_t*,false,stacksingleblock<counter_t,false> > > treecontentalloc;
00079
00080
00081 void reccopytree(fptree_t *target,TYPENAME BUILDTREE::nodeptr_t node, node_t *parent) {
00082
00083 for(TYPENAME BUILDTREE::nodeiter_t i=node->childrenBegin();
00084 i!=node->childrenEnd();
00085 ++i) {
00086
00087
00088 node_t *newnode=nodeallocator.allocate();
00089 newnode->parent=parent;
00090 newnode->item=(*i).first;
00091 newnode->counter=(*i).second->getCounter();
00092 newnode->headerlink=target->headertable[(*i).first];
00093 target->headertable[(*i).first]=newnode;
00094 target->freqs[(*i).first]+=(*i).second->getCounter();
00095
00096 reccopytree(target,TYPENAME BUILDTREE::nodeptr_t((*i).second),newnode);
00097 }
00098 }
00099
00100 void copyBuildTreeToFinalTree(TYPENAME BUILDTREE::buildtree_t &buildtree,fptree_t &fulltree,item_t maxitem) {
00101 alignalloc::allocz(fulltree.freqs,maxitem);
00102 alignalloc::allocz(fulltree.headertable,maxitem);
00103 fulltree.rootfreq=buildtree.getRoot()->getCounter();
00104 reccopytree(&fulltree,(buildtree.getRoot()),NULL);
00105 }
00106
00108 void buildTree(item_t maxitem) {
00109 bracz::nullTreeAnn treeann;
00110 BUILDTREE btr;
00111 typename BUILDTREE::buildtree_t buildtree;
00112 btr.initBuildTree(buildtree,maxitem,treeann);
00113
00114 log_status(0,"Building temporary FP tree.");
00115
00116 std::vector<item_t> trans;
00117 inp->rewind();
00118
00119 transaction_count=0;
00120 while (counter_t count=inp->nextTransactionBIS(trans)) {
00121 transaction_count+=count;
00122 btr.addTransToTree(trans,trans.size(),buildtree,count,treeann);
00123 }
00124 copyBuildTreeToFinalTree(buildtree,fulltree,maxitem);
00125 }
00126
00127
00129 void buildAllL1Trees(item_t maxitem) {
00130 BUILDTREE btr;
00131
00132 bracz::nullTreeAnn treeann;
00133 std::vector<typename BUILDTREE::buildtree_t> trees;
00134 trees.resize(maxitem);
00135 log_status(0,"Initializing FP tree.");
00136 for(item_t i=0;i<maxitem;++i) {
00137 btr.initBuildTree(trees[i],i,treeann);
00138 }
00139 log_status(0,"Building temporary FP trees.");
00140
00141 std::vector<item_t> trans;
00142 inp->rewind();
00143
00144 transaction_count=0;
00145 while (counter_t count=inp->nextTransactionBIS(trans)) {
00146 transaction_count+=count;
00147 for (size_t itemidx=0;itemidx<trans.size();++itemidx) {
00148 btr.addTransToTree(trans,itemidx,trees[trans[itemidx]],count,treeann);
00149 }
00150 }
00151 l1trees.resize(maxitem);
00152 for(item_t i=0;i<maxitem;++i) {
00153 copyBuildTreeToFinalTree(trees[i],l1trees[i],i);
00154 }
00155 }
00156
00157 public:
00158 class SinglePathIterator {
00159 private:
00160 node_t *c;
00161 public:
00162 void DINLINE increment(fptree_t *) {
00163 c=c->parent;
00164 }
00165 bool DINLINE atEnd(fptree_t *) {
00166 return !c;
00167 }
00168 item_t DINLINE getCurrItem(fptree_t *) {
00169 return c->item;
00170 }
00171 SinglePathIterator(node_t *_c): c(_c){}
00172 };
00173
00174 SinglePathIterator getSinglePathIterator(fptree_t *t,item_t curritem) {
00175 return SinglePathIterator(t->headertable[curritem]);
00176 }
00177
00184 ClassicFPStructure(INPUT *_inp, item_t maxitem) {
00185 inp=_inp;
00186 switch(FIRSTLEVEL) {
00187 case FLBuildSingleTree: {
00188 buildTree(maxitem);
00189 break;
00190 }
00191 case FLBuildAllL1Trees: {
00192 buildAllL1Trees(maxitem);
00193 break;
00194 }
00195 case FLSimultProject: {
00196 log_err(0,"Simultaneous projection is not implemented in ClassicFpTree yet.");
00197 exit(1);
00198 break;
00199 }
00200 }
00201 }
00202
00203 fptree_t * getFullTree() {
00204 if (FIRSTLEVEL != FLBuildSingleTree) {
00205 log_err(0,"Requested full tree when per-item trees are calculated!");
00206 return NULL;
00207 } else
00208 return &fulltree;
00209 }
00210
00211 fptree_t * getProjTree(item_t item) {
00212 if (FIRSTLEVEL == FLBuildSingleTree) {
00213 log_err(0,"Requested per-item tree when only unconditional tree is calculated!");
00214 return NULL;
00215 } else
00216 return &(l1trees[item]);
00217 }
00218
00219
00220 item_t DINLINE checkSinglePath(fptree_t *t, item_t curritem, item_t spdepth) {
00221 if (!SINGLE) {
00222 return 0;
00223 } else {
00224 while ((spdepth<curritem) && ((!t->headertable[spdepth]) || (!t->headertable[spdepth]->headerlink)))
00225 spdepth++;
00226 return spdepth;
00227 }
00228 }
00229
00230 template <class O_M> void DINLINE handleSinglePath(fptree_t *t, item_t curritem, O_M *out) {
00231
00232 }
00233
00234 void DINLINE zeroDataDense(fptree_t *intr, item_t curritem) {
00235
00236 alignalloc::zerola(intr->freqs,curritem);
00237
00238
00239
00240
00241
00242
00243 intr->rootfreq=0;
00244 }
00245
00246 void DINLINE aggregateDense(fptree_t *intr, item_t curritem) {
00247 for (node_t *cnode=intr->headertable[curritem];cnode;cnode=cnode->headerlink) {
00248 counter_t c=cnode->counter;
00249 intr->rootfreq+=c;
00250 node_t *nnode=cnode->parent;
00251 while (nnode) {
00252 nnode->counter+=c;
00253 intr->freqs[nnode->item]+=c;
00254 nnode=nnode->parent;
00255 }
00256 }
00257
00258 }
00259
00260 fptree_t * DINLINE projectTree(fptree_t *intr,item_t curritem) {
00261 if (TD) {
00262 zeroDataDense(intr,curritem);
00263 aggregateDense(intr,curritem);
00264 return intr;
00265 } else {
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 }
00280 }
00281
00282 void DINLINE deallocTree(fptree_t *t, fptree_t *parent, item_t projitem) {
00283
00284 if (TD) {
00285 for (node_t *cnode=t->headertable[projitem];cnode;cnode=cnode->headerlink) {
00286 node_t *pnode=cnode;
00287 while (pnode && pnode->counter) {
00288 pnode->counter=0;
00289 pnode=pnode->parent;
00290 }
00291 }
00292 }
00293 }
00294
00295 };
00296
00297 }