1 // See www.openfst.org for extensive documentation on this weighted
2 // finite-state transducer library.
4 // Cartesian power weight semiring operation definitions, using
5 // SparseTupleWeight as underlying representation.
7 #ifndef FST_LIB_SPARSE_POWER_WEIGHT_H_
8 #define FST_LIB_SPARSE_POWER_WEIGHT_H_
13 #include <fst/sparse-tuple-weight.h>
14 #include <fst/weight.h>
19 // Below SparseTupleWeight*Mapper are used in conjunction with
20 // SparseTupleWeightMap to compute the respective semiring operations
21 template <class W, class K>
22 struct SparseTupleWeightPlusMapper {
23 W Map(const K &k, const W &v1, const W &v2) const { return Plus(v1, v2); }
26 template <class W, class K>
27 struct SparseTupleWeightTimesMapper {
28 W Map(const K &k, const W &v1, const W &v2) const { return Times(v1, v2); }
31 template <class W, class K>
32 struct SparseTupleWeightDivideMapper {
33 const DivideType type;
35 explicit SparseTupleWeightDivideMapper(DivideType type_) : type(type_) {}
37 W Map(const K &k, const W &v1, const W &v2) const {
38 return Divide(v1, v2, type);
42 template <class W, class K>
43 struct SparseTupleWeightApproxMapper {
46 explicit SparseTupleWeightApproxMapper(float delta_ = kDelta)
49 W Map(const K &k, const W &v1, const W &v2) const {
50 return ApproxEqual(v1, v2, delta) ? W::One() : W::Zero();
54 // Sparse cartesian power semiring: W ^ n
58 // - a left semimodule when W is a left semiring,
59 // - a right semimodule when W is a right semiring,
60 // - a bisemimodule when W is a semiring,
61 // the free semimodule of rank n over W
63 // The Times operation is overloaded to provide the left and right scalar
66 // K is the key value type. kNoKey (-1) is reserved for internal use
67 template <class W, class K = int>
68 class SparsePowerWeight : public SparseTupleWeight<W, K> {
70 using ReverseWeight = SparsePowerWeight<typename W::ReverseWeight, K>;
72 SparsePowerWeight() {}
74 explicit SparsePowerWeight(const SparseTupleWeight<W, K> &weight)
75 : SparseTupleWeight<W, K>(weight) {}
77 template <class Iterator>
78 SparsePowerWeight(Iterator begin, Iterator end)
79 : SparseTupleWeight<W, K>(begin, end) {}
81 SparsePowerWeight(const K &key, const W &weight)
82 : SparseTupleWeight<W, K>(key, weight) {}
84 static const SparsePowerWeight &Zero() {
85 static const SparsePowerWeight zero(SparseTupleWeight<W, K>::Zero());
89 static const SparsePowerWeight &One() {
90 static const SparsePowerWeight one(SparseTupleWeight<W, K>::One());
94 static const SparsePowerWeight &NoWeight() {
95 static const SparsePowerWeight no_weight(
96 SparseTupleWeight<W, K>::NoWeight());
100 // Overide this: Overwrite the Type method to reflect the key type if using
101 // a non-default key type.
102 static const string &Type() {
105 type = W::Type() + "_^n";
106 if (sizeof(K) != sizeof(uint32)) {
107 type += "_" + std::to_string(CHAR_BIT * sizeof(K));
113 static constexpr uint64 Properties() {
114 return W::Properties() &
115 (kLeftSemiring | kRightSemiring | kCommutative | kIdempotent);
118 SparsePowerWeight Quantize(float delta = kDelta) const {
119 return SparsePowerWeight(SparseTupleWeight<W, K>::Quantize(delta));
122 ReverseWeight Reverse() const {
123 return ReverseWeight(SparseTupleWeight<W, K>::Reverse());
127 // Semimodule plus operation.
128 template <class W, class K>
129 inline SparsePowerWeight<W, K> Plus(const SparsePowerWeight<W, K> &w1,
130 const SparsePowerWeight<W, K> &w2) {
131 SparsePowerWeight<W, K> result;
132 SparseTupleWeightPlusMapper<W, K> operator_mapper;
133 SparseTupleWeightMap(&result, w1, w2, operator_mapper);
137 // Semimodule times operation.
138 template <class W, class K>
139 inline SparsePowerWeight<W, K> Times(const SparsePowerWeight<W, K> &w1,
140 const SparsePowerWeight<W, K> &w2) {
141 SparsePowerWeight<W, K> result;
142 SparseTupleWeightTimesMapper<W, K> operator_mapper;
143 SparseTupleWeightMap(&result, w1, w2, operator_mapper);
147 // Semimodule divide operation.
148 template <class W, class K>
149 inline SparsePowerWeight<W, K> Divide(const SparsePowerWeight<W, K> &w1,
150 const SparsePowerWeight<W, K> &w2,
151 DivideType type = DIVIDE_ANY) {
152 SparsePowerWeight<W, K> result;
153 SparseTupleWeightDivideMapper<W, K> operator_mapper(type);
154 SparseTupleWeightMap(&result, w1, w2, operator_mapper);
158 // Semimodule dot product operation.
159 template <class W, class K>
160 inline const W &DotProduct(const SparsePowerWeight<W, K> &w1,
161 const SparsePowerWeight<W, K> &w2) {
162 const SparsePowerWeight<W, K> product = Times(w1, w2);
164 for (SparseTupleWeightIterator<W, K> it(product); !it.Done(); it.Next()) {
165 result = Plus(result, it.Value().second);
170 template <class W, class K>
171 inline bool ApproxEqual(const SparsePowerWeight<W, K> &w1,
172 const SparsePowerWeight<W, K> &w2,
173 float delta = kDelta) {
174 SparseTupleWeight<W, K> result;
175 SparseTupleWeightApproxMapper<W, K> operator_mapper(kDelta);
176 SparseTupleWeightMap(&result, w1, w2, operator_mapper);
177 return result == SparsePowerWeight<W, K>::One();
180 template <class W, class K>
181 inline SparsePowerWeight<W, K> Times(const W &k,
182 const SparsePowerWeight<W, K> &w2) {
183 const SparseTupleWeight<W, K> t2(k);
184 const SparsePowerWeight<W, K> w1(t2);
185 return Times(w1, w2);
188 template <class W, class K>
189 inline SparsePowerWeight<W, K> Times(const SparsePowerWeight<W, K> &w1,
191 const SparseTupleWeight<W, K> t2(k);
192 const SparsePowerWeight<W, K> w2(t2);
193 return Times(w1, w2);
196 template <class W, class K>
197 inline SparsePowerWeight<W, K> Divide(const SparsePowerWeight<W, K> &w1,
199 DivideType divide_type = DIVIDE_ANY) {
200 const SparseTupleWeight<W, K> t2(k);
201 const SparsePowerWeight<W, K> w2(t2);
202 return Divide(w1, w2, divide_type);
205 // This function object generates weights over the Cartesian power of rank
206 // n over the underlying weight. This is intended primarily for testing.
207 template <class W, class K>
208 class WeightGenerate<SparsePowerWeight<W, K>> {
210 using Weight = SparsePowerWeight<W, K>;
211 using Generate = WeightGenerate<W>;
213 explicit WeightGenerate(bool allow_zero = true,
214 size_t sparse_power_rank = 3)
215 : generate_(allow_zero), sparse_power_rank_(sparse_power_rank) {}
217 Weight operator()() const {
219 for (size_t i = 1; i <= sparse_power_rank_; ++i) {
220 weight.Push(i, generate_(), true);
226 const Generate generate_;
227 const size_t sparse_power_rank_;
232 #endif // FST_LIB_SPARSE_POWER_WEIGHT_H_