Home | History | Annotate | Download | only in fst
      1 // random-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: riley (at) google.com (Michael Riley)
     17 //
     18 // \file
     19 // Function objects to generate random weights in various semirings
     20 // for testing purposes.
     21 
     22 #ifndef FST_LIB_RANDOM_WEIGHT_H__
     23 #define FST_LIB_RANDOM_WEIGHT_H__
     24 
     25 #include <cstdlib>
     26 #include <ctime>
     27 #include <vector>
     28 using std::vector;
     29 
     30 
     31 #include <fst/float-weight.h>
     32 #include <fst/product-weight.h>
     33 #include <fst/string-weight.h>
     34 #include <fst/lexicographic-weight.h>
     35 #include <fst/power-weight.h>
     36 #include <fst/signed-log-weight.h>
     37 #include <fst/sparse-power-weight.h>
     38 
     39 
     40 namespace fst {
     41 
     42 // The boolean 'allow_zero' below determines whether Zero() and zero
     43 // divisors should be returned in the random weight generation.
     44 
     45 // This function object returns TropicalWeightTpl<T>'s that are random integers
     46 // chosen from [0, kNumRandomWeights).
     47 template <class T>
     48 class TropicalWeightGenerator_ {
     49  public:
     50   typedef TropicalWeightTpl<T> Weight;
     51 
     52   TropicalWeightGenerator_(int seed = time(0), bool allow_zero = true)
     53       : allow_zero_(allow_zero) {
     54     srand(seed);
     55   }
     56 
     57   Weight operator() () const {
     58     int n = rand() % (kNumRandomWeights + allow_zero_);
     59     if (allow_zero_ && n == kNumRandomWeights)
     60       return Weight::Zero();
     61 
     62     return Weight(static_cast<T>(n));
     63   }
     64 
     65  private:
     66   // The number of alternative random weights.
     67   static const int kNumRandomWeights = 5;
     68 
     69   bool allow_zero_;  // permit Zero() and zero divisors
     70 };
     71 
     72 template <class T> const int TropicalWeightGenerator_<T>::kNumRandomWeights;
     73 
     74 typedef TropicalWeightGenerator_<float> TropicalWeightGenerator;
     75 
     76 
     77 // This function object returns LogWeightTpl<T>'s that are random integers
     78 // chosen from [0, kNumRandomWeights).
     79 template <class T>
     80 class LogWeightGenerator_ {
     81  public:
     82   typedef LogWeightTpl<T> Weight;
     83 
     84   LogWeightGenerator_(int seed = time(0), bool allow_zero = true)
     85       : allow_zero_(allow_zero) {
     86     srand(seed);
     87   }
     88 
     89   Weight operator() () const {
     90     int n = rand() % (kNumRandomWeights + allow_zero_);
     91     if (allow_zero_ && n == kNumRandomWeights)
     92       return Weight::Zero();
     93 
     94     return Weight(static_cast<T>(n));
     95   }
     96 
     97  private:
     98   // Number of alternative random weights.
     99   static const int kNumRandomWeights = 5;
    100 
    101   bool allow_zero_;  // permit Zero() and zero divisors
    102 };
    103 
    104 template <class T> const int LogWeightGenerator_<T>::kNumRandomWeights;
    105 
    106 typedef LogWeightGenerator_<float> LogWeightGenerator;
    107 
    108 
    109 // This function object returns MinMaxWeightTpl<T>'s that are random integers
    110 // chosen from (-kNumRandomWeights, kNumRandomWeights) in addition to
    111 // One(), and Zero() if zero is allowed.
    112 template <class T>
    113 class MinMaxWeightGenerator_ {
    114  public:
    115   typedef MinMaxWeightTpl<T> Weight;
    116 
    117   MinMaxWeightGenerator_(int seed = time(0), bool allow_zero = true)
    118       : allow_zero_(allow_zero) {
    119     srand(seed);
    120   }
    121 
    122   Weight operator() () const {
    123     int n = (rand() % (2*kNumRandomWeights + allow_zero_)) - kNumRandomWeights;
    124     if (allow_zero_ && n == kNumRandomWeights)
    125       return Weight::Zero();
    126     else if (n == -kNumRandomWeights)
    127       return Weight::One();
    128 
    129     return Weight(static_cast<T>(n));
    130   }
    131 
    132  private:
    133   // Parameters controlling the number of alternative random weights.
    134   static const int kNumRandomWeights = 5;
    135 
    136   bool allow_zero_;  // permit Zero() and zero divisors
    137 };
    138 
    139 template <class T> const int MinMaxWeightGenerator_<T>::kNumRandomWeights;
    140 
    141 typedef MinMaxWeightGenerator_<float> MinMaxWeightGenerator;
    142 
    143 
    144 // This function object returns StringWeights that are random integer
    145 // strings chosen from {1,...,kAlphabetSize}^{0,kMaxStringLength} U { Zero }
    146 template <typename L, StringType S = STRING_LEFT>
    147 class StringWeightGenerator {
    148  public:
    149   typedef StringWeight<L, S> Weight;
    150 
    151   StringWeightGenerator(int seed = time(0), bool allow_zero = true)
    152       : allow_zero_(allow_zero) {
    153      srand(seed);
    154   }
    155 
    156   Weight operator() () const {
    157     int n = rand() % (kMaxStringLength + allow_zero_);
    158     if (allow_zero_ && n == kMaxStringLength)
    159       return Weight::Zero();
    160 
    161     vector<L> v;
    162     for (int i = 0; i < n; ++i)
    163       v.push_back(rand() % kAlphabetSize + 1);
    164     return Weight(v.begin(), v.end());
    165   }
    166 
    167  private:
    168   // Alphabet size for random weights.
    169   static const int kAlphabetSize = 5;
    170   // Number of alternative random weights.
    171   static const int kMaxStringLength = 5;
    172 
    173   bool allow_zero_;  // permit Zero() and zero
    174 };
    175 
    176 template <typename L, StringType S>
    177 const int StringWeightGenerator<L, S>::kAlphabetSize;
    178 template <typename L, StringType S>
    179 const int StringWeightGenerator<L, S>::kMaxStringLength;
    180 
    181 
    182 // This function object returns a weight generator over the product of the
    183 // weights (by default) for the generators G1 and G2.
    184 template <class G1, class G2,
    185   class W = ProductWeight<typename G1::Weight, typename G2::Weight> >
    186 class ProductWeightGenerator {
    187  public:
    188   typedef typename G1::Weight W1;
    189   typedef typename G2::Weight W2;
    190   typedef W Weight;
    191 
    192   ProductWeightGenerator(int seed = time(0), bool allow_zero = true)
    193       : generator1_(seed, allow_zero), generator2_(seed, allow_zero) {}
    194 
    195   Weight operator() () const {
    196     W1 w1 = generator1_();
    197     W2 w2 = generator2_();
    198     return Weight(w1, w2);
    199   }
    200 
    201  private:
    202   G1 generator1_;
    203   G2 generator2_;
    204 };
    205 
    206 
    207 // This function object returns a weight generator for a lexicographic weight
    208 // composed out of weights for the generators G1 and G2. For lexicographic
    209 // weights, we cannot generate zeroes for the two subweights separately:
    210 // weights are members iff both members are zero or both members are non-zero.
    211 template <class G1, class G2>
    212 class LexicographicWeightGenerator {
    213  public:
    214   typedef typename G1::Weight W1;
    215   typedef typename G2::Weight W2;
    216   typedef LexicographicWeight<W1, W2> Weight;
    217 
    218   LexicographicWeightGenerator(int seed = time(0), bool allow_zero = true)
    219       : generator1_(seed, false), generator2_(seed, false),
    220         allow_zero_(allow_zero) {}
    221 
    222   Weight operator() () const {
    223     if (allow_zero_) {
    224       int n = rand() % (kNumRandomWeights + allow_zero_);
    225       if (n == kNumRandomWeights)
    226         return Weight(W1::Zero(), W2::Zero());
    227     }
    228     W1 w1 = generator1_();
    229     W2 w2 = generator2_();
    230     return Weight(w1, w2);
    231   }
    232 
    233  private:
    234   G1 generator1_;
    235   G2 generator2_;
    236   static const int kNumRandomWeights = 5;
    237   bool allow_zero_;
    238 };
    239 
    240 template <class G1, class G2>
    241 const int LexicographicWeightGenerator<G1, G2>::kNumRandomWeights;
    242 
    243 
    244 // Product generator of a string weight generator and an
    245 // arbitrary weight generator.
    246 template <class L, class G, StringType S = STRING_LEFT>
    247 class GallicWeightGenerator
    248     : public ProductWeightGenerator<StringWeightGenerator<L, S>, G> {
    249 
    250  public:
    251   typedef ProductWeightGenerator<StringWeightGenerator<L, S>, G> PG;
    252   typedef typename G::Weight W;
    253   typedef GallicWeight<L, W, S> Weight;
    254 
    255   GallicWeightGenerator(int seed = time(0), bool allow_zero = true)
    256       : PG(seed, allow_zero) {}
    257 
    258   GallicWeightGenerator(const PG &pg) : PG(pg) {}
    259 };
    260 
    261 // This function object returms a weight generator over the catersian power
    262 // of rank n of the weights for the generator G.
    263 template <class G, unsigned int n>
    264 class PowerWeightGenerator {
    265  public:
    266   typedef typename G::Weight W;
    267   typedef PowerWeight<W, n> Weight;
    268 
    269   PowerWeightGenerator(int seed = time(0), bool allow_zero = true)
    270       : generator_(seed, allow_zero) {}
    271 
    272   Weight operator()() const {
    273     Weight w;
    274     for (size_t i = 0; i < n; ++i) {
    275       W r = generator_();
    276       w.SetValue(i, r);
    277     }
    278     return w;
    279   }
    280 
    281  private:
    282   G generator_;
    283 };
    284 
    285 // This function object returns SignedLogWeightTpl<T>'s that are
    286 // random integers chosen from [0, kNumRandomWeights).
    287 // The sign is randomly chosen as well.
    288 template <class T>
    289 class SignedLogWeightGenerator_ {
    290  public:
    291   typedef SignedLogWeightTpl<T> Weight;
    292 
    293   SignedLogWeightGenerator_(int seed = time(0), bool allow_zero = true)
    294   : allow_zero_(allow_zero) {
    295     srand(seed);
    296   }
    297 
    298   Weight operator() () const {
    299     int m = rand() % 2;
    300     int n = rand() % (kNumRandomWeights + allow_zero_);
    301 
    302     return SignedLogWeightTpl<T>(
    303       (m == 0) ?
    304         TropicalWeight(-1.0) :
    305         TropicalWeight(1.0),
    306       (allow_zero_ && n == kNumRandomWeights) ?
    307         LogWeightTpl<T>::Zero() :
    308         LogWeightTpl<T>(static_cast<T>(n)));
    309   }
    310 
    311  private:
    312   // Number of alternative random weights.
    313   static const int kNumRandomWeights = 5;
    314   bool allow_zero_;  // permit Zero() and zero divisors
    315 };
    316 
    317 template <class T> const int SignedLogWeightGenerator_<T>::kNumRandomWeights;
    318 
    319 typedef SignedLogWeightGenerator_<float> SignedLogWeightGenerator;
    320 
    321 // This function object returms a weight generator over the catersian power
    322 // of rank n of the weights for the generator G.
    323 template <class G, class K, unsigned int n>
    324 class SparsePowerWeightGenerator {
    325  public:
    326   typedef typename G::Weight W;
    327   typedef SparsePowerWeight<W, K> Weight;
    328 
    329   SparsePowerWeightGenerator(int seed = time(0), bool allow_zero = true)
    330       : generator_(seed, allow_zero) {}
    331 
    332   Weight operator()() const {
    333     Weight w;
    334     for (size_t i = 1; i <= n; ++i) {
    335       W r = generator_();
    336       K p = i;
    337       w.Push(p, r, true);
    338     }
    339     return w;
    340   }
    341 
    342  private:
    343   G generator_;
    344 };
    345 
    346 }  // namespace fst
    347 
    348 #endif  // FST_LIB_RANDOM_WEIGHT_H__
    349