FST  openfst-1.8.2
OpenFst Library
sparse-tuple-weight.h
Go to the documentation of this file.
1 // Copyright 2005-2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the 'License');
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an 'AS IS' BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // See www.openfst.org for extensive documentation on this weighted
16 // finite-state transducer library.
17 //
18 // Sparse version of tuple-weight, based on tuple-weight.h.
19 // Internally stores sparse key, value pairs in linked list. The default value
20 // element is the assumed value of unset keys. Internal singleton
21 // implementation that stores first key, value pair as a initialized member
22 // variable to avoid unnecessary allocation on heap. Use
23 // SparseTupleWeightIterator to iterate through the key,value pairs. Note:
24 // this does NOT iterate through the default value.
25 //
26 // Sparse tuple weight set operation definitions.
27 
28 #ifndef FST_SPARSE_TUPLE_WEIGHT_H_
29 #define FST_SPARSE_TUPLE_WEIGHT_H_
30 
31 #include <algorithm>
32 #include <list>
33 #include <stack>
34 #include <string>
35 #include <utility>
36 
37 
38 #include <fst/weight.h>
39 
40 
41 namespace fst {
42 
43 template <class W, class K>
45 
46 // Arbitrary dimension tuple weight, stored as a sorted linked-list.
47 // W is any weight class, and K is the key value type. kNoKey (-1) is reserved
48 // for internal use.
49 template <class W, class K = int>
51  public:
53 
55  using Pair = std::pair<K, W>;
56  using Weight = W;
57  using Index = K;
58 
59  static constexpr K kNoKey = -1;
60 
62 
63  ~SparseTupleWeight() noexcept = default;
64 
65  template <class Iterator>
67  Init();
68  // Assumes input iterator is sorted.
69  for (auto it = begin; it != end; ++it) PushBack(*it);
70  }
71 
72  // Initialize component `key` to `weight`, with `default_weight` for all
73  // other components.
74  SparseTupleWeight(const K &key, const W &weight, const W &default_weight)
75  : default_(default_weight),
76  first_(weight == default_weight ? kNoKey : key, weight) {}
77 
78  explicit SparseTupleWeight(const W &weight) { Init(weight); }
79 
81  Init(weight.DefaultValue());
82  SetDefaultValue(weight.DefaultValue());
83  for (Iterator it(weight); !it.Done(); it.Next()) {
84  PushBack(it.Value());
85  }
86  }
87 
89  // Don't move the default, so weight.default_ is still valid.
90  : default_(weight.default_), // NOLINT
91  first_(std::move(weight.first_)),
92  rest_(std::move(weight.rest_)) {
93  // move leaves the source in a valid but unspecified state.
94  // Make sure the source weight is empty.
95  weight.first_ = Pair(kNoKey, W::NoWeight());
96  weight.rest_.clear();
97  }
98 
99  static const SparseTupleWeight &Zero() {
100  static const SparseTupleWeight zero(W::Zero());
101  return zero;
102  }
103 
104  static const SparseTupleWeight &One() {
105  static const SparseTupleWeight one(W::One());
106  return one;
107  }
108 
109  static const SparseTupleWeight &NoWeight() {
110  static const SparseTupleWeight no_weight(W::NoWeight());
111  return no_weight;
112  }
113 
114  std::istream &Read(std::istream &strm) {
115  ReadType(strm, &default_);
116  ReadType(strm, &first_);
117  return ReadType(strm, &rest_);
118  }
119 
120  std::ostream &Write(std::ostream &strm) const {
121  WriteType(strm, default_);
122  WriteType(strm, first_);
123  return WriteType(strm, rest_);
124  }
125 
127  if (this == &weight) return *this; // Checks for identity.
128  Init(weight.DefaultValue());
129  for (Iterator it(weight); !it.Done(); it.Next()) {
130  PushBack(it.Value());
131  }
132  return *this;
133  }
134 
136  if (this == &weight) return *this; // Checks for identity.
137  // Don't move the default, so weight.default_ is still valid.
138  default_ = weight.default_;
139  first_ = std::move(weight.first_);
140  rest_ = std::move(weight.rest_);
141  // move leaves the source in a valid but unspecified state.
142  // Make sure the source weight is empty.
143  weight.first_ = Pair(kNoKey, W::NoWeight());
144  weight.rest_.clear();
145  return *this;
146  }
147 
148  bool Member() const {
149  if (!DefaultValue().Member()) return false;
150  for (Iterator it(*this); !it.Done(); it.Next()) {
151  if (!it.Value().second.Member()) return false;
152  }
153  return true;
154  }
155 
156  // Assumes H() function exists for the hash of the key value.
157  size_t Hash() const {
158  size_t h = 0;
159  static const std::hash<K> H;
160  for (Iterator it(*this); !it.Done(); it.Next()) {
161  h = 5 * h + H(it.Value().first);
162  h = 13 * h + it.Value().second.Hash();
163  }
164  return h;
165  }
166 
167  SparseTupleWeight Quantize(float delta = kDelta) const {
168  SparseTupleWeight weight;
169  for (Iterator it(*this); !it.Done(); it.Next()) {
170  weight.PushBack(it.Value().first, it.Value().second.Quantize(delta));
171  }
172  return weight;
173  }
174 
176  ReverseWeight weight(DefaultValue().Reverse());
177  for (Iterator it(*this); !it.Done(); it.Next()) {
178  weight.PushBack(it.Value().first, it.Value().second.Reverse());
179  }
180  return weight;
181  }
182 
183  void Init(const W &default_value = W::Zero()) {
184  first_ = Pair(kNoKey, W::NoWeight());
185  // Initialized to the reserved key value.
186  default_ = default_value;
187  rest_.clear();
188  }
189 
190  size_t Size() const {
191  if (first_.first == kNoKey) {
192  return 0;
193  } else {
194  return rest_.size() + 1;
195  }
196  }
197 
198  inline void PushBack(const K &key, const W &weight,
199  bool default_value_check = true) {
200  PushBack(std::make_pair(key, weight), default_value_check);
201  }
202 
203  inline void PushBack(const Pair &pair, bool default_value_check = true) {
204  if (default_value_check && pair.second == default_) return;
205  if (first_.first == kNoKey) {
206  first_ = pair;
207  } else {
208  rest_.push_back(pair);
209  }
210  }
211 
212  // Returns the `key`-th component, or the default value if not set.
213  const W &Value(const K &key) const {
214  // TODO(rybach): Consider binary search.
215  Iterator iter(*this);
216  for (; !iter.Done() && iter.Value().first < key; iter.Next()) continue;
217  return !iter.Done() && iter.Value().first == key ? iter.Value().second
218  : DefaultValue();
219  }
220 
221  void SetValue(const K &key, const W &w) {
222  if (w == DefaultValue()) {
223  ClearValue(key);
224  } else {
225  SetValueToNonDefault(key, w);
226  }
227  }
228 
229  void SetDefaultValue(const W &value) { default_ = value; }
230 
231  const W &DefaultValue() const { return default_; }
232 
233  private:
234  void SetValueToNonDefault(const K &key, const W &w) {
235  // Don't use SparseTupleWeightIterator, since that's const.
236  if (first_.first == kNoKey) {
237  first_ = Pair(key, w);
238  } else if (key < first_.first) {
239  rest_.push_front(first_);
240  first_ = Pair(key, w);
241  } else if (key == first_.first) {
242  first_.second = w;
243  } else {
244  const auto i =
245  std::find_if(rest_.begin(), rest_.end(),
246  [key](const Pair &p) { return p.first >= key; });
247  if (i != rest_.end() && i->first == key) {
248  i->second = w;
249  } else {
250  rest_.insert(i, Pair(key, w));
251  }
252  }
253  }
254 
255  // Removes the weight value for `key`, having the effect of setting
256  // it to `DefaultValue()`.
257  void ClearValue(const K &key) {
258  if (key == first_.first) {
259  if (!rest_.empty()) {
260  first_ = rest_.front();
261  rest_.pop_front();
262  } else {
263  first_.first = kNoKey;
264  }
265  } else if (key > first_.first) {
266  const auto i =
267  std::find_if(rest_.begin(), rest_.end(),
268  [key](const Pair &p) { return p.first >= key; });
269  if (i != rest_.end() && i->first == key) {
270  rest_.erase(i);
271  }
272  }
273  }
274 
275  // Assumed default value of uninitialized keys, by default W::Zero().
276  W default_;
277 
278  // Key values pairs are first stored in first_, then fill rest_ this way we
279  // can avoid dynamic allocation in the common case where the weight is a
280  // single key/value pair.
281  Pair first_;
282  std::list<Pair> rest_;
283 
284  friend class SparseTupleWeightIterator<W, K>;
285 };
286 
287 template <class W, class K>
289  public:
291  using const_iterator = typename std::list<Pair>::const_iterator;
292  using iterator = typename std::list<Pair>::iterator;
293 
295  : first_(weight.first_),
296  rest_(weight.rest_),
297  init_(true),
298  iter_(rest_.begin()) {}
299 
300  bool Done() const {
301  if (init_) {
302  return first_.first == SparseTupleWeight<W, K>::kNoKey;
303  } else {
304  return iter_ == rest_.end();
305  }
306  }
307 
308  const Pair &Value() const { return init_ ? first_ : *iter_; }
309 
310  void Next() {
311  if (init_) {
312  init_ = false;
313  } else {
314  ++iter_;
315  }
316  }
317 
318  void Reset() {
319  init_ = true;
320  iter_ = rest_.begin();
321  }
322 
323  private:
324  const Pair &first_;
325  const std::list<Pair> &rest_;
326  bool init_; // In the initialized state?
327  const_iterator iter_;
328 };
329 
330 // M must be callable as a function W(K, W, W).
331 // K will be kNoKey when mapping the default value.
332 template <class W, class K, class M>
334  const SparseTupleWeight<W, K> &w1,
335  const SparseTupleWeight<W, K> &w2,
336  const M &operator_mapper) {
339  const auto &v1_def = w1.DefaultValue();
340  const auto &v2_def = w2.DefaultValue();
341  result->SetDefaultValue(
342  operator_mapper(SparseTupleWeight<W, K>::kNoKey, v1_def, v2_def));
343  while (!w1_it.Done() || !w2_it.Done()) {
344  const auto &k1 = (w1_it.Done()) ? w2_it.Value().first : w1_it.Value().first;
345  const auto &k2 = (w2_it.Done()) ? w1_it.Value().first : w2_it.Value().first;
346  const auto &v1 = (w1_it.Done()) ? v1_def : w1_it.Value().second;
347  const auto &v2 = (w2_it.Done()) ? v2_def : w2_it.Value().second;
348  if (k1 == k2) {
349  result->PushBack(k1, operator_mapper(k1, v1, v2));
350  if (!w1_it.Done()) w1_it.Next();
351  if (!w2_it.Done()) w2_it.Next();
352  } else if (k1 < k2) {
353  result->PushBack(k1, operator_mapper(k1, v1, v2_def));
354  w1_it.Next();
355  } else {
356  result->PushBack(k2, operator_mapper(k2, v1_def, v2));
357  w2_it.Next();
358  }
359  }
360 }
361 
362 template <class W, class K>
363 inline bool operator==(const SparseTupleWeight<W, K> &w1,
364  const SparseTupleWeight<W, K> &w2) {
365  const auto &v1_def = w1.DefaultValue();
366  const auto &v2_def = w2.DefaultValue();
367  if (v1_def != v2_def) return false;
370  while (!w1_it.Done() || !w2_it.Done()) {
371  const auto &k1 = (w1_it.Done()) ? w2_it.Value().first : w1_it.Value().first;
372  const auto &k2 = (w2_it.Done()) ? w1_it.Value().first : w2_it.Value().first;
373  const auto &v1 = (w1_it.Done()) ? v1_def : w1_it.Value().second;
374  const auto &v2 = (w2_it.Done()) ? v2_def : w2_it.Value().second;
375  if (k1 == k2) {
376  if (v1 != v2) return false;
377  if (!w1_it.Done()) w1_it.Next();
378  if (!w2_it.Done()) w2_it.Next();
379  } else if (k1 < k2) {
380  if (v1 != v2_def) return false;
381  w1_it.Next();
382  } else {
383  if (v1_def != v2) return false;
384  w2_it.Next();
385  }
386  }
387  return true;
388 }
389 
390 template <class W, class K>
391 inline bool operator!=(const SparseTupleWeight<W, K> &w1,
392  const SparseTupleWeight<W, K> &w2) {
393  return !(w1 == w2);
394 }
395 
396 template <class W, class K>
397 inline std::ostream &operator<<(std::ostream &strm,
398  const SparseTupleWeight<W, K> &weight) {
399  CompositeWeightWriter writer(strm);
400  writer.WriteBegin();
401  writer.WriteElement(weight.DefaultValue());
402  for (SparseTupleWeightIterator<W, K> it(weight); !it.Done(); it.Next()) {
403  writer.WriteElement(it.Value().first);
404  writer.WriteElement(it.Value().second);
405  }
406  writer.WriteEnd();
407  return strm;
408 }
409 
410 template <class W, class K>
411 inline std::istream &operator>>(std::istream &strm,
412  SparseTupleWeight<W, K> &weight) {
413  CompositeWeightReader reader(strm);
414  reader.ReadBegin();
415  W def;
416  bool more = reader.ReadElement(&def);
417  weight.Init(def);
418  while (more) {
419  K key;
420  reader.ReadElement(&key);
421  W v;
422  more = reader.ReadElement(&v);
423  weight.PushBack(key, v);
424  }
425  reader.ReadEnd();
426  return strm;
427 }
428 
429 } // namespace fst
430 
431 #endif // FST_SPARSE_TUPLE_WEIGHT_H_
void PushBack(const Pair &pair, bool default_value_check=true)
void PushBack(const K &key, const W &weight, bool default_value_check=true)
~SparseTupleWeight() noexcept=default
SparseTupleWeight & operator=(SparseTupleWeight &&weight) noexcept
void Init(const W &default_value=W::Zero())
std::ostream & Write(std::ostream &strm) const
std::pair< K, typename Arc::Weight > Pair
void SparseTupleWeightMap(SparseTupleWeight< W, K > *result, const SparseTupleWeight< W, K > &w1, const SparseTupleWeight< W, K > &w2, const M &operator_mapper)
static const SparseTupleWeight & Zero()
static const SparseTupleWeight & One()
SparseTupleWeightIterator(const SparseTupleWeight< W, K > &weight)
static const SparseTupleWeight & NoWeight()
void SetValue(const K &key, const W &w)
std::ostream & WriteType(std::ostream &strm, const T t)
Definition: util.h:211
std::istream & operator>>(std::istream &strm, FloatWeightTpl< T > &w)
Definition: float-weight.h:181
SparseTupleWeight(Iterator begin, Iterator end)
bool operator!=(const ErrorWeight &, const ErrorWeight &)
Definition: error-weight.h:53
SparseTupleWeight(const K &key, const W &weight, const W &default_weight)
void SetDefaultValue(const W &value)
std::ostream & operator<<(std::ostream &strm, const ErrorWeight &)
Definition: error-weight.h:70
static constexpr K kNoKey
SparseTupleWeight(const W &weight)
typename SparseTupleWeight< W, K >::Pair Pair
const W & DefaultValue() const
SparseTupleWeight & operator=(const SparseTupleWeight &weight)
SparseTupleWeight(const SparseTupleWeight &weight)
typename std::list< Pair >::const_iterator const_iterator
std::istream & Read(std::istream &strm)
bool ReadElement(T *comp, bool last=false)
Definition: weight.h:366
const W & Value(const K &key) const
bool operator==(const ErrorWeight &, const ErrorWeight &)
Definition: error-weight.h:50
SparseTupleWeight Quantize(float delta=kDelta) const
typename std::list< Pair >::iterator iterator
std::istream & ReadType(std::istream &strm, T *t)
Definition: util.h:65
void WriteElement(const T &comp)
Definition: weight.h:316
SparseTupleWeight(SparseTupleWeight &&weight) noexcept
ReverseWeight Reverse() const
constexpr float kDelta
Definition: weight.h:130