1 : #ifndef TAGCOLL_COLL_BASE_TCC
2 : #define TAGCOLL_COLL_BASE_TCC
3 :
4 : /** \file
5 : * Base mixins for tagged collections
6 : */
7 :
8 : /*
9 : * Copyright (C) 2003,2004,2005,2006 Enrico Zini <enrico@debian.org>
10 : *
11 : * This library is free software; you can redistribute it and/or
12 : * modify it under the terms of the GNU Lesser General Public
13 : * License as published by the Free Software Foundation; either
14 : * version 2.1 of the License, or (at your option) any later version.
15 : *
16 : * This library is distributed in the hope that it will be useful,
17 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 : * Lesser General Public License for more details.
20 : *
21 : * You should have received a copy of the GNU Lesser General Public
22 : * License along with this library; if not, write to the Free Software
23 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 : */
25 :
26 : #include <tagcoll/coll/base.h>
27 : #include <tagcoll/utils/set.h>
28 : #include <algorithm>
29 :
30 : namespace tagcoll {
31 : namespace coll {
32 :
33 : template<typename T>
34 : class coll_traits;
35 :
36 : template<typename Self> template<typename COLL>
37 : bool ReadonlyCollection<Self>::RelevanceOrder<COLL>::operator()(
38 : const typename coll_traits<Self>::tag_type& t1,
39 : const typename coll_traits<Self>::tag_type& t2)
40 : {
41 : // New cardinality divided by the square root of the old cardinality.
42 : // The square root is used to downplay the very common tags a bit
43 : int csub1 = second.getCardinality(t1);
44 : float cfull1 = first.getCardinality(t1);
45 : int csub2 = second.getCardinality(t2);
46 : float cfull2 = first.getCardinality(t2);
47 : float rel1 = (float)(csub1 * csub1) / cfull1;
48 : float rel2 = (float)(csub2 * csub2) / cfull2;
49 :
50 : return rel1 < rel2;
51 : // return 10000 * second.getCardinality(t1) / first.getCardinality(t1)
52 : // < 10000 * second.getCardinality(t2) / first.getCardinality(t2);
53 : }
54 :
55 :
56 : template<typename Self>
57 : bool ReadonlyCollection<Self>::hasTag(const typename coll_traits<Self>::tag_type& tag) const
58 : {
59 : return !self().getItemsHavingTag(tag).empty();
60 : }
61 :
62 : template<typename Self> template<typename ITEMS>
63 1 : typename coll_traits<Self>::tagset_type ReadonlyCollection<Self>::getTagsOfItems(const ITEMS& items) const
64 : {
65 : using namespace wibble::operators;
66 1 : typename coll_traits<Self>::tagset_type res;
67 2 : for (typename ITEMS::const_iterator i = items.begin();
68 : i != items.end(); i++)
69 1 : res |= self().getTagsOfItem(*i);
70 0 : return res;
71 : }
72 :
73 : template<typename Self> template<typename TAGS>
74 : typename coll_traits<Self>::itemset_type ReadonlyCollection<Self>::getItemsHavingTags(const TAGS& tags) const
75 : {
76 : using namespace wibble::operators;
77 2 : if (tags.empty())
78 0 : return typename coll_traits<Self>::itemset_type();
79 :
80 2 : typename TAGS::const_iterator i = tags.begin();
81 2 : typename coll_traits<Self>::itemset_type res = self().getItemsHavingTag(*i);
82 :
83 9 : for (++i ; i != tags.end(); ++i)
84 7 : res &= self().getItemsHavingTag(*i);
85 :
86 2 : return res;
87 : }
88 :
89 : template<typename Self>
90 : std::vector<typename coll_traits<Self>::tag_type> ReadonlyCollection<Self>::getAllTagsAsVector() const
91 : {
92 : std::set<typename coll_traits<Self>::tag_type> asSet = self().getAllTags();
93 : std::vector<typename coll_traits<Self>::tag_type> res;
94 : res.reserve(asSet.size());
95 : std::copy(asSet.begin(), asSet.end(), back_inserter(res));
96 : return res;
97 : }
98 :
99 : template<typename Self>
100 : unsigned int ReadonlyCollection<Self>::getCardinality(const typename coll_traits<Self>::tag_type& tag) const
101 : {
102 : return self().getItemsHavingTag(tag).size();
103 : }
104 :
105 : template<typename Self> template<typename TAGS>
106 : typename coll_traits<Self>::tagset_type ReadonlyCollection<Self>::getCompanionTags(const TAGS& tags) const
107 : {
108 : using namespace wibble::operators;
109 : return self().getTagsOfItems(self().getItemsHavingTags(tags)) - tags;
110 : }
111 :
112 : template<typename Self> template<typename TAGS>
113 : typename coll_traits<Self>::itemset_type ReadonlyCollection<Self>::getRelatedItems(const TAGS& tags, int maxdistance) const
114 : {
115 : using namespace wibble::operators;
116 :
117 : typename coll_traits<Self>::itemset_type packages;
118 : typename coll_traits<Self>::itemset_type res;
119 :
120 : // First get a list of packages that have a non-empty intersection with `tags'
121 : for (typename TAGS::const_iterator i = tags.begin(); i != tags.end(); i++)
122 : packages |= self().getItemsHavingTag(*i);
123 :
124 : // Then keep only those within the given distance
125 : for (typename coll_traits<Self>::itemset_type::const_iterator i = packages.begin(); i != packages.end(); i++)
126 : {
127 : int dist = utils::set_distance(tags, self().getTagsOfItem(*i));
128 : if (dist >= 0 && dist <= maxdistance)
129 : res |= *i;
130 : }
131 :
132 : return res;
133 : }
134 :
135 : template<typename Self> template<typename OUT>
136 4 : void ReadonlyCollection<Self>::output(OUT out) const
137 : {
138 126890 : for (typename Self::const_iterator i = self().begin();
139 : i != self().end(); ++i)
140 : {
141 84583 : *out = make_pair(wibble::singleton(i->first), i->second);
142 84587 : ++out;
143 : }
144 9 : }
145 :
146 : template<typename Self> template<typename TAGS, typename OUT>
147 : void ReadonlyCollection<Self>::outputHavingTags(const TAGS& tags, OUT out) const
148 : {
149 : typename coll_traits<Self>::itemset_type items = self().getItemsHavingTags(tags);
150 : for (typename coll_traits<Self>::itemset_type::const_iterator i = items.begin();
151 : i != items.end(); ++i)
152 : {
153 : *out = std::make_pair(wibble::singleton(*i), self().getTagsOfItem(*i));
154 : ++out;
155 : }
156 : }
157 :
158 : template<typename Self>
159 : std::vector<typename coll_traits<Self>::tag_type> ReadonlyCollection<Self>::tagsInCardinalityOrder() const
160 : {
161 : std::vector<typename coll_traits<Self>::tag_type> res = self().getAllTagsAsVector();
162 : std::sort(res.begin(), res.end(), CardinalityOrder(self()));
163 : return res;
164 : }
165 :
166 : template<typename Self>
167 : std::vector<typename coll_traits<Self>::tag_type> ReadonlyCollection<Self>::tagsInDiscriminanceOrder() const
168 : {
169 : std::vector<typename coll_traits<Self>::tag_type> res = self().getAllTagsAsVector();
170 : std::sort(res.begin(), res.end(), DiscriminanceOrder(self()));
171 : return res;
172 : }
173 :
174 : /**
175 : * Get a vector containing all tags in this collection, sorted by
176 : * increasing relevance to the filtering applied between coll and this
177 : * collection
178 : */
179 : template<typename Self> template<typename COLL>
180 : std::vector<typename coll_traits<Self>::tag_type> ReadonlyCollection<Self>::tagsInRelevanceOrder(const COLL& coll) const
181 : {
182 : std::vector<typename coll_traits<Self>::tag_type> res = self().getAllTagsAsVector();
183 : std::sort(res.begin(), res.end(), RelevanceOrder<COLL>(coll, self()));
184 : return res;
185 : }
186 :
187 : }
188 6 : }
189 :
190 : // vim:set ts=4 sw=4:
191 : #endif
|