00001 #ifndef IntersectProPruner_HPP
00002 #define IntersectProPruner_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 sequence
00017 {
00018 namespace inhomogeneous_trie
00019 {
00020 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR>
00021 class IntersectProPruner : public
00022 Bodon::inhomogeneous_trie::ManipulatorBase<DF_D, TRIE, LEAF_ALLOCATOR>
00023 {
00024 private:
00025 typedef Bodon::inhomogeneous_trie::ManipulatorBase<DF_D, TRIE, LEAF_ALLOCATOR> PARENT;
00026 protected:
00027 std::vector<Edge> extenders;
00028 mutable std::vector<item_t> ext_items;
00029 mutable std::vector<item_t> ext_nee;
00030 std::vector<Edge> replace_list;
00031
00032 public:
00033 IntersectProPruner( TRIE& main_trie, DF_D& df_decoder,
00034 LEAF_ALLOCATOR& s_alloc ) :
00035 Bodon::inhomogeneous_trie::ManipulatorBase<DF_D, TRIE, LEAF_ALLOCATOR>(
00036 main_trie, df_decoder, s_alloc){}
00037
00038 protected:
00039
00040 void intersect( const TRIE* subset_trie ) const;
00041
00042 void filterNonExtenders(
00043 const std::vector<const TRIE*>& subset_tries,
00044 const item_t leaf_item ) const;
00045
00046 bool findSubsetTries(
00047 std::vector<item_t>& itemset,
00048 std::vector<const TRIE*>& subset_trie) const;
00049
00050 void generateCandidateAtParent(
00051 TRIE* trie, std::vector<item_t>& maybe_candidate);
00052
00053
00054 };
00055
00056 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR> inline void
00057 IntersectProPruner<DF_D, TRIE, LEAF, LEAF_ALLOCATOR>::
00058 intersect( const TRIE* subset_trie) const
00059 {
00060 typename TRIE::const_iterator it_e( subset_trie->edgelist.begin() );
00061 std::vector<item_t>::iterator it_i(ext_items.begin());
00062 while(it_e != subset_trie->edgelist.end() && it_i != ext_items.end())
00063 {
00064 if(*it_e < *it_i)
00065 ++it_e;
00066 else if(*it_e > *it_i)
00067 it_i = ext_items.erase(it_i);
00068 else
00069 {
00070 ++it_e;
00071 ++it_i;
00072 }
00073 }
00074 ext_items.erase(it_i, ext_items.end());
00075 }
00076
00077
00078 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR> inline void
00079 IntersectProPruner<DF_D, TRIE, LEAF, LEAF_ALLOCATOR>::
00080 filterNonExtenders( const std::vector<const TRIE*>& subset_tries,
00081 const item_t leaf_item ) const
00082 {
00083 std::vector<typename TRIE::const_iterator> subset_child_iters;
00084 subset_child_iters.reserve(subset_tries.size());
00085 for(typename std::vector<const TRIE*>::const_iterator it = subset_tries.begin();
00086 it != subset_tries.end(); ++it)
00087 subset_child_iters.push_back((*it)->edgelist.begin());
00088
00089 for(std::vector<item_t>::size_type index = 0;
00090 index < subset_tries.size(); ++index)
00091 {
00092 while( subset_child_iters[index] != subset_tries[index]->edgelist.end() &&
00093 (*(subset_child_iters[index])).first < leaf_item)
00094 ++subset_child_iters[index];
00095 if( subset_child_iters[index] != subset_tries[index]->edgelist.end() &&
00096 (*(subset_child_iters[index])).first == leaf_item)
00097 intersect(static_cast<const TRIE*>((*(subset_child_iters[index])).second));
00098 else
00099 {
00100 ext_items.clear();
00101 break;
00102 }
00103 }
00104 }
00105
00106
00107 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR> inline bool
00108 IntersectProPruner<DF_D, TRIE, LEAF, LEAF_ALLOCATOR>::
00109 findSubsetTries( std::vector<item_t>& itemset,
00110 std::vector<const TRIE*>& subset_tries ) const
00111 {
00112 assert(itemset.size() > 0);
00113 std::vector<item_t>::iterator item_it = itemset.end()-1;
00114 register item_t deleted_item = *item_it, temp_item;
00115 const TRIE* a_subset_trie;
00116
00117 itemset.pop_back();
00118 a_subset_trie = PARENT::main_trie.isIncluded( itemset, itemset.begin() );
00119 if(a_subset_trie)
00120 subset_tries.push_back(a_subset_trie);
00121 else
00122 {
00123 itemset.push_back(deleted_item);
00124 return false;
00125 }
00126 while(item_it != itemset.begin() )
00127 {
00128 --item_it;
00129 temp_item = *item_it;
00130 *item_it = deleted_item;
00131 deleted_item = temp_item;
00132 a_subset_trie = PARENT::main_trie.isIncluded( itemset, itemset.begin() );
00133 if(a_subset_trie)
00134 subset_tries.push_back(a_subset_trie);
00135 else
00136 {
00137 itemset.insert( item_it, deleted_item );
00138 return false;
00139 }
00140 }
00141 itemset.insert( item_it, deleted_item );
00142 return true;
00143 }
00144
00145 template <class DF_D, class TRIE, class LEAF, class LEAF_ALLOCATOR>
00146 inline void IntersectProPruner<DF_D, TRIE, LEAF, LEAF_ALLOCATOR>::
00147 generateCandidateAtParent(TRIE* trie, std::vector<item_t>& maybe_candidate)
00148 {
00149 std::vector<const TRIE*> subset_tries;
00150 const bool all_subset_included = findSubsetTries(
00151 maybe_candidate, subset_tries);
00152 typename TRIE::iterator itEdge2;
00153 LEAF* toExtendAsLeaf;
00154 TRIE* toExtend;
00155 replace_list.clear();
00156 for( typename TRIE::iterator itEdge( trie->edgelist.begin() );
00157 itEdge != trie->edgelist.end(); ++itEdge )
00158 {
00159 toExtendAsLeaf = static_cast<LEAF*>((*itEdge).second);
00160 PARENT::df_decoder.pushItemWithWrite( (*itEdge).first,
00161 toExtendAsLeaf->getCounter() );
00162 PARENT::df_decoder.popItem();
00163 if(all_subset_included)
00164 {
00165 ext_items.clear();
00166 for( itEdge2 = trie->edgelist.begin();
00167 itEdge2 != trie->edgelist.end(); ++itEdge2 )
00168 ext_items.push_back((*itEdge2).first);
00169 filterNonExtenders( subset_tries, (*itEdge).first );
00170 if(ext_items.empty())
00171 {
00172 toExtendAsLeaf->setCounter(0);
00173 replace_list.push_back(Edge((*itEdge).first, toExtendAsLeaf));
00174 }
00175 else
00176 {
00177 extenders.clear();
00178 for(std::vector<item_t>::iterator it = ext_items.begin();
00179 it != ext_items.end(); ++it)
00180 {
00181 extenders.push_back(Edge(*it, PARENT::s_alloc.allocate()));
00182 static_cast<LEAF*>(extenders.back().second)->setCounter(0);
00183 }
00184 toExtend = new TRIE(toExtendAsLeaf->getCounter());
00185 PARENT::s_alloc.free(toExtendAsLeaf);
00186 replace_list.push_back(Edge((*itEdge).first, toExtend));
00187 toExtend->edgelist.insert(extenders);
00188 }
00189 }
00190 else
00191 {
00192 toExtendAsLeaf->setCounter(0);
00193 replace_list.push_back(Edge((*itEdge).first, toExtendAsLeaf));
00194 }
00195 }
00196 trie->edgelist.clear();
00197 trie->edgelist.insert(replace_list);
00198 }
00199 }
00200 }
00201 }
00202 #endif