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
28namespace 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.
38template <class W, unsigned int n>
39class 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
49  PowerWeight() {}
50
51  PowerWeight(const TupleWeight<W, n> &w) : TupleWeight<W, n>(w) {}
52
53  template <class Iterator>
54  PowerWeight(Iterator begin, Iterator end) : TupleWeight<W, n>(begin, end) {}
55
56  static const PowerWeight<W, n> &Zero() {
57    static const PowerWeight<W, n> zero(TupleWeight<W, n>::Zero());
58    return zero;
59  }
60
61  static const PowerWeight<W, n> &One() {
62    static const PowerWeight<W, n> one(TupleWeight<W, n>::One());
63    return one;
64  }
65
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
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
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
91  ReverseWeight Reverse() const {
92    return TupleWeight<W, n>::Reverse();
93  }
94};
95
96
97// Semiring plus operation
98template <class W, unsigned int n>
99inline 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
108template <class W, unsigned int n>
109inline 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
118template <class W, unsigned int n>
119inline 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
129template <class W, unsigned int n>
130inline 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 w;
135}
136
137// Semimodule right scalar product
138template <class W, unsigned int n>
139inline 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 w;
144}
145
146// Semimodule dot product
147template <class W, unsigned int n>
148inline 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