// random-weight.h // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Copyright 2005-2010 Google, Inc. // Author: riley@google.com (Michael Riley) // // \file // Function objects to generate random weights in various semirings // for testing purposes. #ifndef FST_LIB_RANDOM_WEIGHT_H__ #define FST_LIB_RANDOM_WEIGHT_H__ #include #include #include using std::vector; #include #include #include #include #include #include #include namespace fst { // The boolean 'allow_zero' below determines whether Zero() and zero // divisors should be returned in the random weight generation. // This function object returns TropicalWeightTpl's that are random integers // chosen from [0, kNumRandomWeights). template class TropicalWeightGenerator_ { public: typedef TropicalWeightTpl Weight; TropicalWeightGenerator_(int seed = time(0), bool allow_zero = true) : allow_zero_(allow_zero) { srand(seed); } Weight operator() () const { int n = rand() % (kNumRandomWeights + allow_zero_); if (allow_zero_ && n == kNumRandomWeights) return Weight::Zero(); return Weight(static_cast(n)); } private: // The number of alternative random weights. static const int kNumRandomWeights = 5; bool allow_zero_; // permit Zero() and zero divisors }; template const int TropicalWeightGenerator_::kNumRandomWeights; typedef TropicalWeightGenerator_ TropicalWeightGenerator; // This function object returns LogWeightTpl's that are random integers // chosen from [0, kNumRandomWeights). template class LogWeightGenerator_ { public: typedef LogWeightTpl Weight; LogWeightGenerator_(int seed = time(0), bool allow_zero = true) : allow_zero_(allow_zero) { srand(seed); } Weight operator() () const { int n = rand() % (kNumRandomWeights + allow_zero_); if (allow_zero_ && n == kNumRandomWeights) return Weight::Zero(); return Weight(static_cast(n)); } private: // Number of alternative random weights. static const int kNumRandomWeights = 5; bool allow_zero_; // permit Zero() and zero divisors }; template const int LogWeightGenerator_::kNumRandomWeights; typedef LogWeightGenerator_ LogWeightGenerator; // This function object returns MinMaxWeightTpl's that are random integers // chosen from (-kNumRandomWeights, kNumRandomWeights) in addition to // One(), and Zero() if zero is allowed. template class MinMaxWeightGenerator_ { public: typedef MinMaxWeightTpl Weight; MinMaxWeightGenerator_(int seed = time(0), bool allow_zero = true) : allow_zero_(allow_zero) { srand(seed); } Weight operator() () const { int n = (rand() % (2*kNumRandomWeights + allow_zero_)) - kNumRandomWeights; if (allow_zero_ && n == kNumRandomWeights) return Weight::Zero(); else if (n == -kNumRandomWeights) return Weight::One(); return Weight(static_cast(n)); } private: // Parameters controlling the number of alternative random weights. static const int kNumRandomWeights = 5; bool allow_zero_; // permit Zero() and zero divisors }; template const int MinMaxWeightGenerator_::kNumRandomWeights; typedef MinMaxWeightGenerator_ MinMaxWeightGenerator; // This function object returns StringWeights that are random integer // strings chosen from {1,...,kAlphabetSize}^{0,kMaxStringLength} U { Zero } template class StringWeightGenerator { public: typedef StringWeight Weight; StringWeightGenerator(int seed = time(0), bool allow_zero = true) : allow_zero_(allow_zero) { srand(seed); } Weight operator() () const { int n = rand() % (kMaxStringLength + allow_zero_); if (allow_zero_ && n == kMaxStringLength) return Weight::Zero(); vector v; for (int i = 0; i < n; ++i) v.push_back(rand() % kAlphabetSize + 1); return Weight(v.begin(), v.end()); } private: // Alphabet size for random weights. static const int kAlphabetSize = 5; // Number of alternative random weights. static const int kMaxStringLength = 5; bool allow_zero_; // permit Zero() and zero }; template const int StringWeightGenerator::kAlphabetSize; template const int StringWeightGenerator::kMaxStringLength; // This function object returns a weight generator over the product of the // weights (by default) for the generators G1 and G2. template > class ProductWeightGenerator { public: typedef typename G1::Weight W1; typedef typename G2::Weight W2; typedef W Weight; ProductWeightGenerator(int seed = time(0), bool allow_zero = true) : generator1_(seed, allow_zero), generator2_(seed, allow_zero) {} Weight operator() () const { W1 w1 = generator1_(); W2 w2 = generator2_(); return Weight(w1, w2); } private: G1 generator1_; G2 generator2_; }; // This function object returns a weight generator for a lexicographic weight // composed out of weights for the generators G1 and G2. For lexicographic // weights, we cannot generate zeroes for the two subweights separately: // weights are members iff both members are zero or both members are non-zero. template class LexicographicWeightGenerator { public: typedef typename G1::Weight W1; typedef typename G2::Weight W2; typedef LexicographicWeight Weight; LexicographicWeightGenerator(int seed = time(0), bool allow_zero = true) : generator1_(seed, false), generator2_(seed, false), allow_zero_(allow_zero) {} Weight operator() () const { if (allow_zero_) { int n = rand() % (kNumRandomWeights + allow_zero_); if (n == kNumRandomWeights) return Weight(W1::Zero(), W2::Zero()); } W1 w1 = generator1_(); W2 w2 = generator2_(); return Weight(w1, w2); } private: G1 generator1_; G2 generator2_; static const int kNumRandomWeights = 5; bool allow_zero_; }; template const int LexicographicWeightGenerator::kNumRandomWeights; // Product generator of a string weight generator and an // arbitrary weight generator. template class GallicWeightGenerator : public ProductWeightGenerator, G> { public: typedef ProductWeightGenerator, G> PG; typedef typename G::Weight W; typedef GallicWeight Weight; GallicWeightGenerator(int seed = time(0), bool allow_zero = true) : PG(seed, allow_zero) {} GallicWeightGenerator(const PG &pg) : PG(pg) {} }; // This function object returms a weight generator over the catersian power // of rank n of the weights for the generator G. template class PowerWeightGenerator { public: typedef typename G::Weight W; typedef PowerWeight Weight; PowerWeightGenerator(int seed = time(0), bool allow_zero = true) : generator_(seed, allow_zero) {} Weight operator()() const { Weight w; for (size_t i = 0; i < n; ++i) { W r = generator_(); w.SetValue(i, r); } return w; } private: G generator_; }; // This function object returns SignedLogWeightTpl's that are // random integers chosen from [0, kNumRandomWeights). // The sign is randomly chosen as well. template class SignedLogWeightGenerator_ { public: typedef SignedLogWeightTpl Weight; SignedLogWeightGenerator_(int seed = time(0), bool allow_zero = true) : allow_zero_(allow_zero) { srand(seed); } Weight operator() () const { int m = rand() % 2; int n = rand() % (kNumRandomWeights + allow_zero_); return SignedLogWeightTpl( (m == 0) ? TropicalWeight(-1.0) : TropicalWeight(1.0), (allow_zero_ && n == kNumRandomWeights) ? LogWeightTpl::Zero() : LogWeightTpl(static_cast(n))); } private: // Number of alternative random weights. static const int kNumRandomWeights = 5; bool allow_zero_; // permit Zero() and zero divisors }; template const int SignedLogWeightGenerator_::kNumRandomWeights; typedef SignedLogWeightGenerator_ SignedLogWeightGenerator; // This function object returms a weight generator over the catersian power // of rank n of the weights for the generator G. template class SparsePowerWeightGenerator { public: typedef typename G::Weight W; typedef SparsePowerWeight Weight; SparsePowerWeightGenerator(int seed = time(0), bool allow_zero = true) : generator_(seed, allow_zero) {} Weight operator()() const { Weight w; for (size_t i = 1; i <= n; ++i) { W r = generator_(); K p = i; w.Push(p, r, true); } return w; } private: G generator_; }; } // namespace fst #endif // FST_LIB_RANDOM_WEIGHT_H__