1 // power-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: allauzen@google.com (Cyril Allauzen)
17 //
18 // \file
19 // Cartesian power weight semiring operation definitions.
20 
21 #ifndef FST_LIB_POWER_WEIGHT_H__
22 #define FST_LIB_POWER_WEIGHT_H__
23 
24 #include <fst/tuple-weight.h>
25 #include <fst/weight.h>
26 
27 
28 namespace fst {
29 
30 // Cartesian power semiring: W ^ n
31 // Forms:
32 //  - a left semimodule when W is a left semiring,
33 //  - a right semimodule when W is a right semiring,
34 //  - a bisemimodule when W is a semiring,
35 //    the free semimodule of rank n over W
36 // The Times operation is overloaded to provide the
37 // left and right scalar products.
38 template <class W, unsigned int n>
39 class PowerWeight : public TupleWeight<W, n> {
40  public:
41   using TupleWeight<W, n>::Zero;
42   using TupleWeight<W, n>::One;
43   using TupleWeight<W, n>::NoWeight;
44   using TupleWeight<W, n>::Quantize;
45   using TupleWeight<W, n>::Reverse;
46 
47   typedef PowerWeight<typename W::ReverseWeight, n> ReverseWeight;
48 
PowerWeight()49   PowerWeight() {}
50 
PowerWeight(const TupleWeight<W,n> & w)51   PowerWeight(const TupleWeight<W, n> &w) : TupleWeight<W, n>(w) {}
52 
53   template <class Iterator>
PowerWeight(Iterator begin,Iterator end)54   PowerWeight(Iterator begin, Iterator end) : TupleWeight<W, n>(begin, end) {}
55 
Zero()56   static const PowerWeight<W, n> &Zero() {
57     static const PowerWeight<W, n> zero(TupleWeight<W, n>::Zero());
58     return zero;
59   }
60 
One()61   static const PowerWeight<W, n> &One() {
62     static const PowerWeight<W, n> one(TupleWeight<W, n>::One());
63     return one;
64   }
65 
NoWeight()66   static const PowerWeight<W, n> &NoWeight() {
67     static const PowerWeight<W, n> no_weight(TupleWeight<W, n>::NoWeight());
68     return no_weight;
69   }
70 
Type()71   static const string &Type() {
72     static string type;
73     if (type.empty()) {
74       string power;
75       Int64ToStr(n, &power);
76       type = W::Type() + "_^" + power;
77     }
78     return type;
79   }
80 
Properties()81   static uint64 Properties() {
82     uint64 props = W::Properties();
83     return props & (kLeftSemiring | kRightSemiring |
84                     kCommutative | kIdempotent);
85   }
86 
87   PowerWeight<W, n> Quantize(float delta = kDelta) const {
88     return TupleWeight<W, n>::Quantize(delta);
89   }
90 
Reverse()91   ReverseWeight Reverse() const {
92     return TupleWeight<W, n>::Reverse();
93   }
94 };
95 
96 
97 // Semiring plus operation
98 template <class W, unsigned int n>
Plus(const PowerWeight<W,n> & w1,const PowerWeight<W,n> & w2)99 inline PowerWeight<W, n> Plus(const PowerWeight<W, n> &w1,
100                               const PowerWeight<W, n> &w2) {
101   PowerWeight<W, n> w;
102   for (size_t i = 0; i < n; ++i)
103     w.SetValue(i, Plus(w1.Value(i), w2.Value(i)));
104   return w;
105 }
106 
107 // Semiring times operation
108 template <class W, unsigned int n>
Times(const PowerWeight<W,n> & w1,const PowerWeight<W,n> & w2)109 inline PowerWeight<W, n> Times(const PowerWeight<W, n> &w1,
110                                const PowerWeight<W, n> &w2) {
111   PowerWeight<W, n> w;
112   for (size_t i = 0; i < n; ++i)
113     w.SetValue(i, Times(w1.Value(i), w2.Value(i)));
114   return w;
115 }
116 
117 // Semiring divide operation
118 template <class W, unsigned int n>
119 inline PowerWeight<W, n> Divide(const PowerWeight<W, n> &w1,
120                                 const PowerWeight<W, n> &w2,
121                                 DivideType type = DIVIDE_ANY) {
122   PowerWeight<W, n> w;
123   for (size_t i = 0; i < n; ++i)
124     w.SetValue(i, Divide(w1.Value(i), w2.Value(i), type));
125   return w;
126 }
127 
128 // Semimodule left scalar product
129 template <class W, unsigned int n>
Times(const W & s,const PowerWeight<W,n> & w)130 inline PowerWeight<W, n> Times(const W &s, const PowerWeight<W, n> &w) {
131   PowerWeight<W, n> sw;
132   for (size_t i = 0; i < n; ++i)
133     sw.SetValue(i, Times(s, w.Value(i)));
134   return sw;
135 }
136 
137 // Semimodule right scalar product
138 template <class W, unsigned int n>
Times(const PowerWeight<W,n> & w,const W & s)139 inline PowerWeight<W, n> Times(const PowerWeight<W, n> &w, const W &s) {
140   PowerWeight<W, n> ws;
141   for (size_t i = 0; i < n; ++i)
142     ws.SetValue(i, Times(w.Value(i), s));
143   return ws;
144 }
145 
146 // Semimodule dot product
147 template <class W, unsigned int n>
DotProduct(const PowerWeight<W,n> & w1,const PowerWeight<W,n> & w2)148 inline W DotProduct(const PowerWeight<W, n> &w1,
149                     const PowerWeight<W, n> &w2) {
150   W w = W::Zero();
151   for (size_t i = 0; i < n; ++i)
152     w = Plus(w, Times(w1.Value(i), w2.Value(i)));
153   return w;
154 }
155 
156 
157 }  // namespace fst
158 
159 #endif  // FST_LIB_POWER_WEIGHT_H__
160