00001 #ifndef SimplePruner_HPP
00002 #define SimplePruner_HPP
00003
00004 #include "common.hpp"
00005 #include "common/Edge.hpp"
00006 #include "apriori/bodon/inhomogeneous_trie/trie_manipulators/ManipulatorBase.hpp"
00007 #include <vector>
00008
00009
00010
00011
00012
00013
00014 namespace Bodon
00015 {
00016 namespace inhomogeneous_trie
00017 {
00018 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR,
00019 NEELevel NEE, bool DEADENDPRUNE = true>
00020 class SimplePruner : public ManipulatorBase<DF_D, TRIE, LEAF_ALLOCATOR>
00021 {
00022 protected:
00023 typedef ManipulatorBase<DF_D, TRIE, LEAF_ALLOCATOR> PARENT;
00024 std::vector<Edge> extenders;
00025 vector<item_t> leaf_neelist;
00026 std::vector<Edge> replace_list;
00027
00028 bool is_there_any_new_candidate;
00029
00030 public:
00031 SimplePruner( TRIE& main_trie, DF_D& df_decoder,
00032 LEAF_ALLOCATOR& s_alloc ) :
00033 PARENT(main_trie, df_decoder, s_alloc){}
00034
00035
00036 protected:
00037 int helper_func(const TRIE* trie, const item_t new_item) const;
00039 int isAllSubsetFrequent( std::vector<item_t>& maybe_candidate,
00040 const item_t new_item ) const;
00041
00042
00043 void generateCandidateAtParent(
00044 TRIE* trie, std::vector<item_t>& maybe_candidate );
00045 void generateCandidateAtParentNEE(
00046 TRIE* trie, std::vector<item_t>& maybe_candidate,
00047 std::vector<item_t>& NEEsum );
00048 void generateCandidateAtParentNEENoDeadend(
00049 TRIE* trie, std::vector<item_t>& maybe_candidate );
00050 };
00051
00052 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR,
00053 NEELevel NEE, bool DEADENDPRUNE>
00054 inline int SimplePruner<DF_D, TRIE, LEAF, LEAF_ALLOCATOR, NEE, DEADENDPRUNE>::
00055 helper_func( const TRIE* temp_trie, const item_t new_item) const
00056 {
00057 if(NEE > NEE_Off && temp_trie->neeFind(new_item))
00058 {
00059 if(NEE == NEE_Level1)
00060 return 1;
00061 else
00062 {
00063
00064 return 2;
00065 }
00066 }
00067 else
00068 return 0;
00069 }
00070
00071
00072 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR,
00073 NEELevel NEE, bool DEADENDPRUNE>
00074 inline int SimplePruner<DF_D, TRIE, LEAF, LEAF_ALLOCATOR, NEE, DEADENDPRUNE>::
00075 isAllSubsetFrequent( std::vector<item_t>& generator, const item_t new_item ) const
00076 {
00077 assert(itemset.size() > 1);
00078 std::vector<item_t>::iterator item_it = generator.end()-2;
00079 register item_t deleted_item = *item_it, temp_item;
00080 const TRIE* temp_trie;
00081
00082 generator.erase( item_it );
00083 temp_trie = this->main_trie.isIncluded( generator, generator.begin() );
00084 if( temp_trie)
00085 {
00086 if( !temp_trie->edgelist.find(new_item) )
00087 {
00088 generator.insert( item_it, deleted_item );
00089 return helper_func(temp_trie, new_item);
00090 }
00091 }
00092 else
00093 {
00094 generator.insert( item_it, deleted_item );
00095 return 0;
00096 }
00097 while(item_it != generator.begin())
00098 {
00099 --item_it;
00100 temp_item = *item_it;
00101 *item_it = deleted_item;
00102 deleted_item = temp_item;
00103 temp_trie = this->main_trie.isIncluded( generator, generator.begin() );
00104 if( temp_trie)
00105 {
00106 if( !temp_trie->edgelist.find(new_item) )
00107 {
00108 generator.insert( item_it, deleted_item );
00109 return helper_func(temp_trie, new_item);
00110 }
00111 }
00112 else
00113 {
00114 generator.insert( item_it, deleted_item );
00115 return 0;
00116 }
00117 }
00118 generator.insert( item_it, deleted_item );
00119 return 1;
00120 }
00121
00122
00123 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR,
00124 NEELevel NEE, bool DEADENDPRUNE> inline void
00125 SimplePruner<DF_D, TRIE, LEAF, LEAF_ALLOCATOR, NEE, DEADENDPRUNE>::
00126 generateCandidateAtParent(TRIE* trie, std::vector<item_t>& maybe_candidate)
00127 {
00128 typename TRIE::iterator itEdge2;
00129 LEAF* toExtendAsLeaf;
00130 TRIE* toExtend;
00131 replace_list.clear();
00132 for( typename TRIE::iterator itEdge( trie->edgelist.begin() );
00133 itEdge != trie->edgelist.end(); ++itEdge )
00134 {
00135 toExtendAsLeaf = static_cast<LEAF*>((*itEdge).second);
00136 PARENT::df_decoder.pushItemWithWrite( (*itEdge).first,
00137 toExtendAsLeaf->getCounter() );
00138 PARENT::df_decoder.popItem();
00139 maybe_candidate.push_back((*itEdge).first);
00140 itEdge2 = itEdge;
00141 ++itEdge2;
00142 extenders.clear();
00143 for( ; itEdge2 != trie->edgelist.end(); ++itEdge2 )
00144 {
00145 if( isAllSubsetFrequent( maybe_candidate, (*itEdge2).first ) == 1 )
00146 {
00147 extenders.push_back(Edge((*itEdge2).first, PARENT::s_alloc.allocate()));
00148 static_cast<LEAF*>(extenders.back().second)->setCounter(0);
00149 }
00150 }
00151 maybe_candidate.pop_back();
00152
00153 if(!extenders.empty())
00154 {
00155 toExtend = new TRIE(toExtendAsLeaf->getCounter());
00156 replace_list.push_back(Edge((*itEdge).first, toExtend));
00157 toExtend->edgelist.insert(extenders);
00158 if( !DEADENDPRUNE)
00159 is_there_any_new_candidate = true;
00160
00161 }
00162 PARENT::s_alloc.free(toExtendAsLeaf);
00163 }
00164 trie->edgelist.clear();
00165 trie->edgelist.insert(replace_list);
00166 }
00167
00168 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR,
00169 NEELevel NEE, bool DEADENDPRUNE> inline void
00170 SimplePruner<DF_D, TRIE, LEAF, LEAF_ALLOCATOR, NEE, DEADENDPRUNE>::
00171 generateCandidateAtParentNEE( TRIE* trie, std::vector<item_t>& maybe_candidate,
00172 std::vector<item_t>& NEEsum )
00173 {
00174 typename TRIE::iterator itEdge2;
00175 LEAF* toExtendAsLeaf;
00176 TRIE* toExtend;
00177 replace_list.clear();
00178 for( typename TRIE::iterator itEdge( trie->edgelist.begin() );
00179 itEdge != trie->edgelist.end(); ++itEdge )
00180 {
00181 maybe_candidate.push_back((*itEdge).first);
00182 itEdge2 = itEdge;
00183 ++itEdge2;
00184 extenders.clear();
00185 leaf_neelist.clear();
00186 toExtendAsLeaf = static_cast<LEAF*>((*itEdge).second);
00187 for( ; itEdge2 != trie->edgelist.end(); ++itEdge2 )
00188 {
00189 switch (isAllSubsetFrequent( maybe_candidate, (*itEdge2).first ))
00190 {
00191 case 1:
00192 extenders.push_back(Edge((*itEdge2).first, PARENT::s_alloc.allocate()));
00193 static_cast<LEAF*>(extenders.back().second)->setCounter(0);
00194 break;
00195 case 2:
00196 leaf_neelist.push_back((*itEdge2).first);
00197 break;
00198 }
00199 }
00200 maybe_candidate.pop_back();
00201 if(extenders.empty() && leaf_neelist.empty() &&
00202 ( NEE == NEE_Full ||
00203 NEE == NEE_Level1 && PARENT::df_decoder.EEListEmpty()) )
00204
00205 {
00206 PARENT::df_decoder.pushItemWithWrite(
00207 (*itEdge).first, toExtendAsLeaf->getCounter() );
00208 PARENT::df_decoder.popItem();
00209 }
00210 else
00211 {
00212 toExtend = new TRIE(toExtendAsLeaf->getCounter());
00213 toExtend->edgelist.insert(extenders);
00214 toExtend->neePushBackSorted( leaf_neelist );
00215 replace_list.push_back(Edge((*itEdge).first, toExtend));
00216
00217 }
00218 PARENT::s_alloc.free(toExtendAsLeaf);
00219 }
00220 trie->edgelist.clear();
00221 trie->edgelist.insert(replace_list);
00222 }
00223
00224 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR,
00225 NEELevel NEE, bool DEADENDPRUNE> inline void
00226 SimplePruner<DF_D, TRIE, LEAF, LEAF_ALLOCATOR, NEE, DEADENDPRUNE>::
00227 generateCandidateAtParentNEENoDeadend( TRIE* trie, std::vector<item_t>& maybe_candidate )
00228 {
00229 typename TRIE::iterator itEdge2;
00230 LEAF* toExtendAsLeaf;
00231 TRIE* toExtend;
00232 replace_list.clear();
00233 for( typename TRIE::iterator itEdge( trie->edgelist.begin() );
00234 itEdge != trie->edgelist.end(); ++itEdge )
00235 {
00236 maybe_candidate.push_back((*itEdge).first);
00237 itEdge2 = itEdge;
00238 ++itEdge2;
00239 extenders.clear();
00240 leaf_neelist.clear();
00241 toExtendAsLeaf = static_cast<LEAF*>((*itEdge).second);
00242 for( ; itEdge2 != trie->edgelist.end(); ++itEdge2 )
00243 {
00244 switch (isAllSubsetFrequent( maybe_candidate, (*itEdge2).first ))
00245 {
00246 case 1:
00247 extenders.push_back(Edge((*itEdge2).first, PARENT::s_alloc.allocate()));
00248 static_cast<LEAF*>(extenders.back().second)->setCounter(0);
00249 break;
00250 case 2:
00251 leaf_neelist.push_back((*itEdge2).first);
00252 break;
00253 }
00254 }
00255 maybe_candidate.pop_back();
00256 toExtend = new TRIE(toExtendAsLeaf->getCounter());
00257 toExtend->edgelist.insert(extenders);
00258 toExtend->neePushBackSorted( leaf_neelist );
00259 replace_list.push_back(Edge((*itEdge).first, toExtend));
00260 is_there_any_new_candidate = true;
00261 PARENT::s_alloc.free(toExtendAsLeaf);
00262 }
00263 trie->edgelist.clear();
00264 trie->edgelist.insert(replace_list);
00265 }
00266 }
00267 }
00268 #endif