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