00001 /// weight.h 00002 00003 /// Licensed under the Apache License, Version 2.0 (the "License"); 00004 /// you may not use this file except in compliance with the License. 00005 /// You may obtain a copy of the License at 00006 /// 00007 /// http://www.apache.org/licenses/LICENSE-2.0 00008 /// 00009 /// Unless required by applicable law or agreed to in writing, software 00010 /// distributed under the License is distributed on an "AS IS" BASIS, 00011 /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 /// See the License for the specific language governing permissions and 00013 /// limitations under the License. 00014 /// 00015 /// Copyright 2005-2010 Google, Inc. 00016 /// Author: riley@google.com (Michael Riley) 00017 /// 00018 /// \file 00019 /// General weight set and associated semiring operation definitions. 00020 /// 00021 /// A semiring is specified by two binary operations Plus and Times and 00022 /// two designated elements Zero and One with the following properties: 00023 /// Plus: associative, commutative, and has Zero as its identity. 00024 /// Times: associative and has identity One, distributes w.r.t. Plus, and 00025 /// has Zero as an annihilator: 00026 /// Times(Zero(), a) == Times(a, Zero()) = Zero(). 00027 /// 00028 /// A left semiring distributes on the left; a right semiring is 00029 /// similarly defined. 00030 /// 00031 /// A Weight class is required to be (at least) a left or right semiring. 00032 /// 00033 /// In addition, the following should be defined for a Weight: 00034 /// Member: predicate on set membership. 00035 /// >>: reads weight. 00036 /// <<: prints weight. 00037 /// Read(istream &strm): reads from an input stream. 00038 /// Write(ostream &strm): writes to an output stream. 00039 /// Hash: maps weight to size_t. 00040 /// ApproxEqual: approximate equality (for inexact weights) 00041 /// Quantize: quantizes wrt delta (for inexact weights) 00042 /// Divide: for all a,b,c s.t. Times(a, b) == c 00043 /// --> b' = Divide(c, a, DIVIDE_LEFT) if a left semiring, b'.Member() 00044 /// and Times(a, b') == c 00045 /// --> a' = Divide(c, b, DIVIDE_RIGHT) if a right semiring, a'.Member() 00046 /// and Times(a', b) == c 00047 /// --> b' = Divide(c, a) 00048 /// = Divide(c, a, DIVIDE_ANY) 00049 /// = Divide(c, a, DIVIDE_LEFT) 00050 /// = Divide(c, a, DIVIDE_RIGHT) if a commutative semiring, 00051 /// b'.Member() and Times(a, b') == Times(b', a) == c 00052 /// ReverseWeight: the type of the corresponding reverse weight. 00053 /// Typically the same type as Weight for a (both left and right) semiring. 00054 /// For the left string semiring, it is the right string semiring. 00055 /// Reverse: a mapping from Weight to ReverseWeight s.t. 00056 /// --> Reverse(Reverse(a)) = a 00057 /// --> Reverse(Plus(a, b)) = Plus(Reverse(a), Reverse(b)) 00058 /// --> Reverse(Times(a, b)) = Times(Reverse(b), Reverse(a)) 00059 /// Typically the identity mapping in a (both left and right) semiring. 00060 /// In the left string semiring, it maps to the reverse string 00061 /// in the right string semiring. 00062 /// Properties: specifies additional properties that hold: 00063 /// LeftSemiring: indicates weights form a left semiring. 00064 /// RightSemiring: indicates weights form a right semiring. 00065 /// Commutative: for all a,b: Times(a,b) == Times(b,a) 00066 /// Idempotent: for all a: Plus(a, a) == a. 00067 /// Path Property: for all a, b: Plus(a, b) == a or Plus(a, b) == b. 00068 00069 00070 #ifndef FST_LIB_WEIGHT_H__ 00071 #define FST_LIB_WEIGHT_H__ 00072 00073 #include <cmath> 00074 #include <cctype> 00075 #include <iostream> 00076 #include <sstream> 00077 00078 #include <fst/compat.h> 00079 #include <fst/util.h> 00080 00081 namespace fst { 00082 00083 /// 00084 /// CONSTANT DEFINITIONS 00085 /// 00086 00087 /// A representable float near .001 00088 const float kDelta = 1.0F/1024.0F; 00089 00090 /// For all a,b,c: Times(c, Plus(a,b)) = Plus(Times(c,a), Times(c, b)) 00091 const uint64 kLeftSemiring = 0x0000000000000001ULL; 00092 00093 /// For all a,b,c: Times(Plus(a,b), c) = Plus(Times(a,c), Times(b, c)) 00094 const uint64 kRightSemiring = 0x0000000000000002ULL; 00095 00096 const uint64 kSemiring = kLeftSemiring | kRightSemiring; 00097 00098 /// For all a,b: Times(a,b) = Times(b,a) 00099 const uint64 kCommutative = 0x0000000000000004ULL; 00100 00101 /// For all a: Plus(a, a) = a 00102 const uint64 kIdempotent = 0x0000000000000008ULL; 00103 00104 /// For all a,b: Plus(a,b) = a or Plus(a,b) = b 00105 const uint64 kPath = 0x0000000000000010ULL; 00106 00107 00108 /// Determines direction of division. 00109 enum DivideType { DIVIDE_LEFT, /// left division 00110 DIVIDE_RIGHT, /// right division 00111 DIVIDE_ANY }; ///< division in a commutative semiring 00112 00113 /// NATURAL ORDER 00114 /// 00115 /// By definition: 00116 /// a <= b iff a + b = a 00117 /// The natural order is a monotonic and negative partial order iff the 00118 /// semiring is idempotent and (left and right) distributive. It is a 00119 /// total order iff the semiring has the path property. See Mohri, 00120 /// "Semiring Framework and Algorithms for Shortest-Distance Problems", 00121 /// Journal of Automata, Languages and Combinatorics 7(3):321-350, 00122 /// 2002. We define the strict version of this order below. 00123 00124 template <class W> 00125 class NaturalLess { 00126 public: 00127 typedef W Weight; 00128 00129 NaturalLess() { 00130 uint64 props = kIdempotent | kLeftSemiring | kRightSemiring; 00131 if ((W::Properties() & props) != props) 00132 LOG(ERROR) << "NaturalLess: Weight type is not idempotent and " 00133 << "(left and right) distributive: " << W::Type(); 00134 } 00135 00136 bool operator()(const W &w1, const W &w2) const { 00137 return (Plus(w1, w2) == w1) && w1 != w2; 00138 } 00139 }; 00140 00141 00142 /// Power is the iterated product for arbitrary semirings such that 00143 /// Power(w, 0) is One() for the semiring, and 00144 /// Power(w, n) = Times(Power(w, n-1), w) 00145 00146 template <class W> 00147 W Power(W w, size_t n) { 00148 W result = W::One(); 00149 for (size_t i = 0; i < n; ++i) { 00150 result = Times(result, w); 00151 } 00152 return result; 00153 } 00154 00155 } /// namespace fst; 00156 00157 #endif /// FST_LIB_WEIGHT_H__ 00158
1.7.1