1 // See www.openfst.org for extensive documentation on this weighted
2 // finite-state transducer library.
4 // Sparse version of tuple-weight, based on tuple-weight.h.
5 // Internally stores sparse key, value pairs in linked list. The default value
6 // element is the assumed value of unset keys. Internal singleton
7 // implementation that stores first key, value pair as a initialized member
8 // variable to avoid unnecessary allocation on heap. Use
9 // SparseTupleWeightIterator to iterate through the key,value pairs. Note:
10 // this does NOT iterate through the default value.
12 // Sparse tuple weight set operation definitions.
14 #ifndef FST_LIB_SPARSE_TUPLE_WEIGHT_H_
15 #define FST_LIB_SPARSE_TUPLE_WEIGHT_H_
20 #include <unordered_map>
24 #include <fst/weight.h>
29 template <class W, class K>
30 class SparseTupleWeightIterator;
32 // Arbitrary dimension tuple weight, stored as a sorted linked-list.
33 // W is any weight class, and K is the key value type. kNoKey (-1) is reserved
35 template <class W, class K = int>
36 class SparseTupleWeight {
38 using ReverseWeight = SparseTupleWeight<typename W::ReverseWeight, K>;
40 using Pair = std::pair<K, W>;
42 constexpr static K kNoKey = -1;
44 SparseTupleWeight() { Init(); }
46 template <class Iterator>
47 SparseTupleWeight(Iterator begin, Iterator end) {
49 // Assumes input iterator is sorted.
50 for (auto it = begin; it != end; ++it) Push(*it);
53 SparseTupleWeight(const K &key, const W &weight) {
58 explicit SparseTupleWeight(const W &weight) { Init(weight); }
60 SparseTupleWeight(const SparseTupleWeight &weight) {
61 Init(weight.DefaultValue());
62 SetDefaultValue(weight.DefaultValue());
63 for (SparseTupleWeightIterator<W, K> it(weight); !it.Done(); it.Next()) {
68 static const SparseTupleWeight &Zero() {
69 static const SparseTupleWeight zero(W::Zero());
73 static const SparseTupleWeight &One() {
74 static const SparseTupleWeight one(W::One());
78 static const SparseTupleWeight &NoWeight() {
79 static const SparseTupleWeight no_weight(W::NoWeight());
83 std::istream &Read(std::istream &strm) {
84 ReadType(strm, &default_);
85 ReadType(strm, &first_);
86 return ReadType(strm, &rest_);
89 std::ostream &Write(std::ostream &strm) const {
90 WriteType(strm, default_);
91 WriteType(strm, first_);
92 return WriteType(strm, rest_);
95 SparseTupleWeight &operator=(const SparseTupleWeight &weight) {
96 if (this == &weight) return *this; // Checks for identity.
97 Init(weight.DefaultValue());
98 for (SparseTupleWeightIterator<W, K> it(weight); !it.Done(); it.Next()) {
104 bool Member() const {
105 if (!DefaultValue().Member()) return false;
106 for (SparseTupleWeightIterator<W, K> it(*this); !it.Done(); it.Next()) {
107 if (!it.Value().second.Member()) return false;
112 // Assumes H() function exists for the hash of the key value.
113 size_t Hash() const {
115 static const std::hash<K> H;
116 for (SparseTupleWeightIterator<W, K> it(*this); !it.Done(); it.Next()) {
117 h = 5 * h + H(it.Value().first);
118 h = 13 * h + it.Value().second.Hash();
123 SparseTupleWeight Quantize(float delta = kDelta) const {
124 SparseTupleWeight weight;
125 for (SparseTupleWeightIterator<W, K> it(*this); !it.Done(); it.Next()) {
126 weight.Push(it.Value().first, it.Value().second.Quantize(delta));
131 ReverseWeight Reverse() const {
132 SparseTupleWeight weight;
133 for (SparseTupleWeightIterator<W, K> it(*this); !it.Done(); it.Next()) {
134 weight.Push(it.Value().first, it.Value().second.Reverse());
136 return ReverseWeight(weight);
139 void Init(const W &default_value = W::Zero()) {
140 first_.first = kNoKey;
141 // Initialized to the reserved key value.
142 default_ = default_value;
146 size_t Size() const {
147 if (first_.first == kNoKey) {
150 return rest_.size() + 1;
154 inline void Push(const K &key, const W &weight,
155 bool default_value_check = true) {
156 Push(std::make_pair(key, weight), default_value_check);
159 inline void Push(const Pair &pair, bool default_value_check = true) {
160 if (default_value_check && pair.second == default_) return;
161 if (first_.first == kNoKey) {
164 rest_.push_back(pair);
168 void SetDefaultValue(const W &value) { default_ = value; }
170 const W &DefaultValue() const { return default_; }
173 // Assumed default value of uninitialized keys, by default W::Zero().
176 // Key values pairs are first stored in first_, then fill rest_ this way we
177 // can avoid dynamic allocation in the common case where the weight is a
178 // single key/value pair.
180 std::list<Pair> rest_;
182 friend class SparseTupleWeightIterator<W, K>;
185 template <class W, class K>
186 class SparseTupleWeightIterator {
188 using Pair = typename SparseTupleWeight<W, K>::Pair;
189 using const_iterator = typename std::list<Pair>::const_iterator;
190 using iterator = typename std::list<Pair>::iterator;
192 explicit SparseTupleWeightIterator(const SparseTupleWeight<W, K> &weight)
193 : first_(weight.first_),
196 iter_(rest_.begin()) {}
200 return first_.first == SparseTupleWeight<W, K>::kNoKey;
202 return iter_ == rest_.end();
206 const Pair &Value() const { return init_ ? first_ : *iter_; }
218 iter_ = rest_.begin();
223 const std::list<Pair> &rest_;
224 bool init_; // In the initialized state?
225 const_iterator iter_;
228 template <class W, class K, class M>
229 inline void SparseTupleWeightMap(SparseTupleWeight<W, K> *result,
230 const SparseTupleWeight<W, K> &w1,
231 const SparseTupleWeight<W, K> &w2,
232 const M &operator_mapper) {
233 SparseTupleWeightIterator<W, K> w1_it(w1);
234 SparseTupleWeightIterator<W, K> w2_it(w2);
235 const auto &v1_def = w1.DefaultValue();
236 const auto &v2_def = w2.DefaultValue();
237 result->SetDefaultValue(operator_mapper.Map(0, v1_def, v2_def));
238 while (!w1_it.Done() || !w2_it.Done()) {
239 const auto &k1 = (w1_it.Done()) ? w2_it.Value().first : w1_it.Value().first;
240 const auto &k2 = (w2_it.Done()) ? w1_it.Value().first : w2_it.Value().first;
241 const auto &v1 = (w1_it.Done()) ? v1_def : w1_it.Value().second;
242 const auto &v2 = (w2_it.Done()) ? v2_def : w2_it.Value().second;
244 result->Push(k1, operator_mapper.Map(k1, v1, v2));
245 if (!w1_it.Done()) w1_it.Next();
246 if (!w2_it.Done()) w2_it.Next();
247 } else if (k1 < k2) {
248 result->Push(k1, operator_mapper.Map(k1, v1, v2_def));
251 result->Push(k2, operator_mapper.Map(k2, v1_def, v2));
257 template <class W, class K>
258 inline bool operator==(const SparseTupleWeight<W, K> &w1,
259 const SparseTupleWeight<W, K> &w2) {
260 const auto &v1_def = w1.DefaultValue();
261 const auto &v2_def = w2.DefaultValue();
262 if (v1_def != v2_def) return false;
263 SparseTupleWeightIterator<W, K> w1_it(w1);
264 SparseTupleWeightIterator<W, K> w2_it(w2);
265 while (!w1_it.Done() || !w2_it.Done()) {
266 const auto &k1 = (w1_it.Done()) ? w2_it.Value().first : w1_it.Value().first;
267 const auto &k2 = (w2_it.Done()) ? w1_it.Value().first : w2_it.Value().first;
268 const auto &v1 = (w1_it.Done()) ? v1_def : w1_it.Value().second;
269 const auto &v2 = (w2_it.Done()) ? v2_def : w2_it.Value().second;
271 if (v1 != v2) return false;
272 if (!w1_it.Done()) w1_it.Next();
273 if (!w2_it.Done()) w2_it.Next();
274 } else if (k1 < k2) {
275 if (v1 != v2_def) return false;
278 if (v1_def != v2) return false;
285 template <class W, class K>
286 inline bool operator!=(const SparseTupleWeight<W, K> &w1,
287 const SparseTupleWeight<W, K> &w2) {
291 template <class W, class K>
292 inline std::ostream &operator<<(std::ostream &strm,
293 const SparseTupleWeight<W, K> &weight) {
294 CompositeWeightWriter writer(strm);
296 writer.WriteElement(weight.DefaultValue());
297 for (SparseTupleWeightIterator<W, K> it(weight); !it.Done(); it.Next()) {
298 writer.WriteElement(it.Value().first);
299 writer.WriteElement(it.Value().second);
305 template <class W, class K>
306 inline std::istream &operator>>(std::istream &strm,
307 SparseTupleWeight<W, K> &weight) {
308 CompositeWeightReader reader(strm);
311 bool more = reader.ReadElement(&def);
315 reader.ReadElement(&key);
317 more = reader.ReadElement(&v);
326 #endif // FST_LIB_SPARSE_TUPLE_WEIGHT_H_