Home | History | Annotate | Download | only in lib
      1 // product-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 //
     16 // \file
     17 // Product weight set and associated semiring operation definitions.
     18 
     19 #ifndef FST_LIB_PRODUCT_WEIGHT_H__
     20 #define FST_LIB_PRODUCT_WEIGHT_H__
     21 
     22 #include "fst/lib/weight.h"
     23 
     24 DECLARE_string(fst_product_separator);
     25 
     26 namespace fst {
     27 
     28 // Product semiring: W1 * W2
     29 template<class W1, class W2>
     30 class ProductWeight {
     31  public:
     32   typedef ProductWeight<typename W1::ReverseWeight, typename W2::ReverseWeight>
     33   ReverseWeight;
     34 
     35   ProductWeight() {}
     36 
     37   ProductWeight(W1 w1, W2 w2) : value1_(w1), value2_(w2) {}
     38 
     39   static const ProductWeight<W1, W2> &Zero() {
     40     static const ProductWeight<W1, W2> zero(W1::Zero(), W2::Zero());
     41     return zero;
     42   }
     43 
     44   static const ProductWeight<W1, W2> &One() {
     45     static const ProductWeight<W1, W2> one(W1::One(), W2::One());
     46     return one;
     47   }
     48 
     49   static const string &Type() {
     50     static const string type = W1::Type() + "_X_" + W2::Type();
     51     return type;
     52   }
     53 
     54   istream &Read(istream &strm) {
     55     value1_.Read(strm);
     56     return value2_.Read(strm);
     57   }
     58 
     59   ostream &Write(ostream &strm) const {
     60     value1_.Write(strm);
     61     return value2_.Write(strm);
     62   }
     63 
     64   ProductWeight<W1, W2> &operator=(const ProductWeight<W1, W2> &w) {
     65     value1_ = w.Value1();
     66     value2_ = w.Value2();
     67     return *this;
     68   }
     69 
     70   bool Member() const { return value1_.Member() && value2_.Member(); }
     71 
     72   ssize_t Hash() const {
     73     ssize_t h1 = value1_.Hash();
     74     ssize_t h2 = value2_.Hash();
     75     int lshift = 5;
     76     int rshift = sizeof(ssize_t) - 5;
     77     return h1 << lshift ^ h1 >> rshift ^ h2;
     78   }
     79 
     80   ProductWeight<W1, W2> Quantize(float delta = kDelta) const {
     81     return ProductWeight<W1, W2>(value1_.Quantize(), value2_.Quantize());
     82   }
     83 
     84   ReverseWeight Reverse() const {
     85     return ReverseWeight(value1_.Reverse(), value2_.Reverse());
     86   }
     87 
     88   static uint64 Properties() {
     89     uint64 props1 = W1::Properties();
     90     uint64 props2 = W2::Properties();
     91     return props1 & props2 & (kLeftSemiring | kRightSemiring |
     92                               kCommutative | kIdempotent);
     93   }
     94 
     95   W1 Value1() const { return value1_; }
     96 
     97   W2 Value2() const { return value2_; }
     98 
     99  private:
    100   W1 value1_;
    101   W2 value2_;
    102 };
    103 
    104 template <class W1, class W2>
    105 inline bool operator==(const ProductWeight<W1, W2> &w,
    106                        const ProductWeight<W1, W2> &v) {
    107   return w.Value1() == v.Value1() && w.Value2() == v.Value2();
    108 }
    109 
    110 template <class W1, class W2>
    111 inline bool operator!=(const ProductWeight<W1, W2> &w1,
    112                        const ProductWeight<W1, W2> &w2) {
    113   return w1.Value1() != w2.Value1() || w1.Value2() != w2.Value2();
    114 }
    115 
    116 
    117 template <class W1, class W2>
    118 inline bool ApproxEqual(const ProductWeight<W1, W2> &w1,
    119                         const ProductWeight<W1, W2> &w2,
    120                         float delta = kDelta) {
    121   return w1 == w2;
    122 }
    123 
    124 template <class W1, class W2>
    125 inline ostream &operator<<(ostream &strm, const ProductWeight<W1, W2> &w) {
    126   CHECK(FLAGS_fst_product_separator.size() == 1);
    127   char separator = FLAGS_fst_product_separator[0];
    128   return strm << w.Value1() << separator << w.Value2();
    129 }
    130 
    131 template <class W1, class W2>
    132 inline istream &operator>>(istream &strm, ProductWeight<W1, W2> &w) {
    133   CHECK(FLAGS_fst_product_separator.size() == 1);
    134   char separator = FLAGS_fst_product_separator[0];
    135   int c;
    136 
    137   // read any initial whitespapce
    138   while (true) {
    139     c = strm.get();
    140     if (c == EOF || c == separator) {
    141       strm.clear(std::ios::badbit);
    142       return strm;
    143     }
    144     if (!isspace(c))
    145       break;
    146   }
    147 
    148   // read first element
    149   string s1;
    150   do {
    151     s1 += c;
    152     c = strm.get();
    153     if (c == EOF || isspace(c)) {
    154       strm.clear(std::ios::badbit);
    155       return strm;
    156     }
    157   } while (c != separator);
    158   istringstream strm1(s1);
    159   W1 w1 = W1::Zero();
    160   strm1 >> w1;
    161 
    162   // read second element
    163   W2 w2 = W2::Zero();
    164   strm >> w2;
    165 
    166   w = ProductWeight<W1, W2>(w1, w2);
    167   return strm;
    168 }
    169 
    170 template <class W1, class W2>
    171 inline ProductWeight<W1, W2> Plus(const ProductWeight<W1, W2> &w,
    172                                   const ProductWeight<W1, W2> &v) {
    173   return ProductWeight<W1, W2>(Plus(w.Value1(), v.Value1()),
    174                                Plus(w.Value2(), v.Value2()));
    175 }
    176 
    177 template <class W1, class W2>
    178 inline ProductWeight<W1, W2> Times(const ProductWeight<W1, W2> &w,
    179                                    const ProductWeight<W1, W2> &v) {
    180   return ProductWeight<W1, W2>(Times(w.Value1(), v.Value1()),
    181                                Times(w.Value2(), v.Value2()));
    182 }
    183 
    184 template <class W1, class W2>
    185 inline ProductWeight<W1, W2> Divide(const ProductWeight<W1, W2> &w,
    186                                     const ProductWeight<W1, W2> &v,
    187                                     DivideType typ = DIVIDE_ANY) {
    188   return ProductWeight<W1, W2>(Divide(w.Value1(), v.Value1(), typ),
    189                                Divide(w.Value2(), v.Value2(), typ));
    190 }
    191 
    192 }  // namespace fst;
    193 
    194 #endif  // FST_LIB_PRODUCT_WEIGHT_H__
    195