1 // tuple-weight.h
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 // Copyright 2005-2010 Google, Inc.
16 // Author: allauzen@google (Cyril Allauzen)
17 //
18 // \file
19 // Tuple weight set operation definitions.
20 
21 #ifndef FST_LIB_TUPLE_WEIGHT_H__
22 #define FST_LIB_TUPLE_WEIGHT_H__
23 
24 #include <string>
25 #include <vector>
26 using std::vector;
27 
28 #include <fst/weight.h>
29 
30 
31 DECLARE_string(fst_weight_parentheses);
32 DECLARE_string(fst_weight_separator);
33 
34 namespace fst {
35 
36 template<class W, unsigned int n> class TupleWeight;
37 template <class W, unsigned int n>
38 istream &operator>>(istream &strm, TupleWeight<W, n> &w);
39 
40 // n-tuple weight, element of the n-th catersian power of W
41 template <class W, unsigned int n>
42 class TupleWeight {
43  public:
44   typedef TupleWeight<typename W::ReverseWeight, n> ReverseWeight;
45 
TupleWeight()46   TupleWeight() {}
47 
TupleWeight(const TupleWeight & w)48   TupleWeight(const TupleWeight &w) {
49     for (size_t i = 0; i < n; ++i)
50       values_[i] = w.values_[i];
51   }
52 
53   template <class Iterator>
TupleWeight(Iterator begin,Iterator end)54   TupleWeight(Iterator begin, Iterator end) {
55     for (Iterator iter = begin; iter != end; ++iter)
56       values_[iter - begin] = *iter;
57   }
58 
TupleWeight(const W & w)59   TupleWeight(const W &w) {
60     for (size_t i = 0; i < n; ++i)
61       values_[i] = w;
62   }
63 
Zero()64   static const TupleWeight<W, n> &Zero() {
65     static const TupleWeight<W, n> zero(W::Zero());
66     return zero;
67   }
68 
One()69   static const TupleWeight<W, n> &One() {
70     static const TupleWeight<W, n> one(W::One());
71     return one;
72   }
73 
NoWeight()74   static const TupleWeight<W, n> &NoWeight() {
75     static const TupleWeight<W, n> no_weight(W::NoWeight());
76     return no_weight;
77   }
78 
Length()79   static unsigned int Length() {
80     return n;
81   }
82 
Read(istream & strm)83   istream &Read(istream &strm) {
84     for (size_t i = 0; i < n; ++i)
85       values_[i].Read(strm);
86     return strm;
87   }
88 
Write(ostream & strm)89   ostream &Write(ostream &strm) const {
90     for (size_t i = 0; i < n; ++i)
91       values_[i].Write(strm);
92     return strm;
93   }
94 
95   TupleWeight<W, n> &operator=(const TupleWeight<W, n> &w) {
96     for (size_t i = 0; i < n; ++i)
97       values_[i] = w.values_[i];
98     return *this;
99   }
100 
Member()101   bool Member() const {
102     bool member = true;
103     for (size_t i = 0; i < n; ++i)
104       member = member && values_[i].Member();
105     return member;
106   }
107 
Hash()108   size_t Hash() const {
109     uint64 hash = 0;
110     for (size_t i = 0; i < n; ++i)
111       hash = 5 * hash + values_[i].Hash();
112     return size_t(hash);
113   }
114 
115   TupleWeight<W, n> Quantize(float delta = kDelta) const {
116     TupleWeight<W, n> w;
117     for (size_t i = 0; i < n; ++i)
118       w.values_[i] = values_[i].Quantize(delta);
119     return w;
120   }
121 
Reverse()122   ReverseWeight Reverse() const {
123     TupleWeight<W, n> w;
124     for (size_t i = 0; i < n; ++i)
125       w.values_[i] = values_[i].Reverse();
126     return w;
127   }
128 
Value(size_t i)129   const W& Value(size_t i) const { return values_[i]; }
130 
SetValue(size_t i,const W & w)131   void SetValue(size_t i, const W &w) { values_[i] = w; }
132 
133  protected:
134   // Reads TupleWeight when there are no parentheses around tuple terms
ReadNoParen(istream & strm,TupleWeight<W,n> & w,char separator)135   inline static istream &ReadNoParen(istream &strm,
136                                      TupleWeight<W, n> &w,
137                                      char separator) {
138     int c;
139     do {
140       c = strm.get();
141     } while (isspace(c));
142 
143     for (size_t i = 0; i < n - 1; ++i) {
144       string s;
145       if (i)
146         c = strm.get();
147       while (c != separator) {
148         if (c == EOF) {
149           strm.clear(std::ios::badbit);
150           return strm;
151         }
152         s += c;
153         c = strm.get();
154       }
155       // read (i+1)-th element
156       istringstream sstrm(s);
157       W r = W::Zero();
158       sstrm >> r;
159       w.SetValue(i, r);
160     }
161 
162     // read n-th element
163     W r = W::Zero();
164     strm >> r;
165     w.SetValue(n - 1, r);
166 
167     return strm;
168   }
169 
170   // Reads TupleWeight when there are parentheses around tuple terms
ReadWithParen(istream & strm,TupleWeight<W,n> & w,char separator,char open_paren,char close_paren)171   inline static istream &ReadWithParen(istream &strm,
172                                        TupleWeight<W, n> &w,
173                                        char separator,
174                                        char open_paren,
175                                        char close_paren) {
176     int c;
177     do {
178       c = strm.get();
179     } while (isspace(c));
180 
181     if (c != open_paren) {
182       FSTERROR() << " is fst_weight_parentheses flag set correcty? ";
183       strm.clear(std::ios::badbit);
184       return strm;
185     }
186 
187     for (size_t i = 0; i < n - 1; ++i) {
188       // read (i+1)-th element
189       stack<int> parens;
190       string s;
191       c = strm.get();
192       while (c != separator || !parens.empty()) {
193         if (c == EOF) {
194           strm.clear(std::ios::badbit);
195           return strm;
196         }
197         s += c;
198         // if parens encountered before separator, they must be matched
199         if (c == open_paren) {
200           parens.push(1);
201         } else if (c == close_paren) {
202           // Fail for mismatched parens
203           if (parens.empty()) {
204             strm.clear(std::ios::failbit);
205             return strm;
206           }
207           parens.pop();
208         }
209         c = strm.get();
210       }
211       istringstream sstrm(s);
212       W r = W::Zero();
213       sstrm >> r;
214       w.SetValue(i, r);
215     }
216 
217     // read n-th element
218     string s;
219     c = strm.get();
220     while (c != EOF) {
221       s += c;
222       c = strm.get();
223     }
224     if (s.empty() || *s.rbegin() != close_paren) {
225       FSTERROR() << " is fst_weight_parentheses flag set correcty? ";
226       strm.clear(std::ios::failbit);
227       return strm;
228     }
229     s.erase(s.size() - 1, 1);
230     istringstream sstrm(s);
231     W r = W::Zero();
232     sstrm >> r;
233     w.SetValue(n - 1, r);
234 
235     return strm;
236   }
237 
238 
239  private:
240   W values_[n];
241 
242   friend istream &operator>><W, n>(istream&, TupleWeight<W, n>&);
243 };
244 
245 template <class W, unsigned int n>
246 inline bool operator==(const TupleWeight<W, n> &w1,
247                        const TupleWeight<W, n> &w2) {
248   bool equal = true;
249   for (size_t i = 0; i < n; ++i)
250     equal = equal && (w1.Value(i) == w2.Value(i));
251   return equal;
252 }
253 
254 template <class W, unsigned int n>
255 inline bool operator!=(const TupleWeight<W, n> &w1,
256                        const TupleWeight<W, n> &w2) {
257   bool not_equal = false;
258   for (size_t i = 0; (i < n) && !not_equal; ++i)
259     not_equal = not_equal || (w1.Value(i) != w2.Value(i));
260   return not_equal;
261 }
262 
263 template <class W, unsigned int n>
264 inline bool ApproxEqual(const TupleWeight<W, n> &w1,
265                         const TupleWeight<W, n> &w2,
266                         float delta = kDelta) {
267   bool approx_equal = true;
268   for (size_t i = 0; i < n; ++i)
269     approx_equal = approx_equal &&
270         ApproxEqual(w1.Value(i), w2.Value(i), delta);
271   return approx_equal;
272 }
273 
274 template <class W, unsigned int n>
275 inline ostream &operator<<(ostream &strm, const TupleWeight<W, n> &w) {
276   if(FLAGS_fst_weight_separator.size() != 1) {
277     FSTERROR() << "FLAGS_fst_weight_separator.size() is not equal to 1";
278     strm.clear(std::ios::badbit);
279     return strm;
280   }
281   char separator = FLAGS_fst_weight_separator[0];
282   bool write_parens = false;
283   if (!FLAGS_fst_weight_parentheses.empty()) {
284     if (FLAGS_fst_weight_parentheses.size() != 2) {
285       FSTERROR() << "FLAGS_fst_weight_parentheses.size() is not equal to 2";
286       strm.clear(std::ios::badbit);
287       return strm;
288     }
289     write_parens = true;
290   }
291 
292   if (write_parens)
293     strm << FLAGS_fst_weight_parentheses[0];
294   for (size_t i  = 0; i < n; ++i) {
295     if(i)
296       strm << separator;
297     strm << w.Value(i);
298   }
299   if (write_parens)
300     strm << FLAGS_fst_weight_parentheses[1];
301 
302   return strm;
303 }
304 
305 template <class W, unsigned int n>
306 inline istream &operator>>(istream &strm, TupleWeight<W, n> &w) {
307   if(FLAGS_fst_weight_separator.size() != 1) {
308     FSTERROR() << "FLAGS_fst_weight_separator.size() is not equal to 1";
309     strm.clear(std::ios::badbit);
310     return strm;
311   }
312   char separator = FLAGS_fst_weight_separator[0];
313 
314   if (!FLAGS_fst_weight_parentheses.empty()) {
315     if (FLAGS_fst_weight_parentheses.size() != 2) {
316       FSTERROR() << "FLAGS_fst_weight_parentheses.size() is not equal to 2";
317       strm.clear(std::ios::badbit);
318       return strm;
319     }
320     return TupleWeight<W, n>::ReadWithParen(
321         strm, w, separator, FLAGS_fst_weight_parentheses[0],
322         FLAGS_fst_weight_parentheses[1]);
323   } else {
324     return TupleWeight<W, n>::ReadNoParen(strm, w, separator);
325   }
326 }
327 
328 
329 
330 }  // namespace fst
331 
332 #endif  // FST_LIB_TUPLE_WEIGHT_H__
333