• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // complement.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 //
16 // \file
17 // Class to complement an Fst.
18 
19 #ifndef FST_LIB_COMPLEMENT_H__
20 #define FST_LIB_COMPLEMENT_H__
21 
22 #include <algorithm>
23 
24 #include "fst/lib/fst.h"
25 #include "fst/lib/test-properties.h"
26 
27 namespace fst {
28 
29 template <class A> class ComplementFst;
30 
31 // Implementation of delayed ComplementFst. The algorithm used
32 // completes the (deterministic) FSA and then exchanges final and
33 // non-final states.  Completion, i.e. ensuring that all labels can be
34 // read from every state, is accomplished by using RHO labels, which
35 // match all labels that are otherwise not found leaving a state. The
36 // first state in the output is reserved to be a new state that is the
37 // destination of all RHO labels. Each remaining output state s
38 // corresponds to input state s - 1. The first arc in the output at
39 // these states is the rho label, the remaining arcs correspond to the
40 // input arcs.
41 template<class A>
42 class ComplementFstImpl : public FstImpl<A> {
43  public:
44   using FstImpl<A>::SetType;
45   using FstImpl<A>::SetProperties;
46   using FstImpl<A>::Properties;
47   using FstImpl<A>::SetInputSymbols;
48   using FstImpl<A>::SetOutputSymbols;
49 
50   friend class StateIterator< ComplementFst<A> >;
51   friend class ArcIterator< ComplementFst<A> >;
52 
53   typedef typename A::Label Label;
54   typedef typename A::Weight Weight;
55   typedef typename A::StateId StateId;
56 
ComplementFstImpl(const Fst<A> & fst)57   explicit ComplementFstImpl(const Fst<A> &fst) : fst_(fst.Copy()) {
58     SetType("complement");
59     uint64 props = fst.Properties(kILabelSorted, false);
60     SetProperties(ComplementProperties(props), kCopyProperties);
61     SetInputSymbols(fst.InputSymbols());
62     SetOutputSymbols(fst.OutputSymbols());
63   }
64 
~ComplementFstImpl()65   ~ComplementFstImpl() { delete fst_; }
66 
Start()67   StateId Start() const {
68     StateId start = fst_->Start();
69     if (start != kNoStateId)
70       return start + 1;
71     else
72       return 0;
73   }
74 
75   // Exchange final and non-final states; make rho destination state final.
Final(StateId s)76   Weight Final(StateId s) const {
77     if (s == 0 || fst_->Final(s - 1) == Weight::Zero())
78       return Weight::One();
79     else
80       return Weight::Zero();
81   }
82 
NumArcs(StateId s)83   size_t NumArcs(StateId s) const {
84     if (s == 0)
85       return 1;
86     else
87       return fst_->NumArcs(s - 1) + 1;
88   }
89 
NumInputEpsilons(StateId s)90   size_t NumInputEpsilons(StateId s) const {
91     return s == 0 ? 0 : fst_->NumInputEpsilons(s - 1);
92   }
93 
NumOutputEpsilons(StateId s)94   size_t NumOutputEpsilons(StateId s) const {
95     return s == 0 ? 0 : fst_->NumOutputEpsilons(s - 1);
96   }
97 
98  private:
99   const Fst<A> *fst_;
100 
101   DISALLOW_EVIL_CONSTRUCTORS(ComplementFstImpl);
102 };
103 
104 
105 // Complements an automaton; this is a library-internal operation
106 // that introduces the rho label. This version is a delayed Fst.
107 template <class A>
108 class ComplementFst : public Fst<A> {
109  public:
110   friend class StateIterator< ComplementFst<A> >;
111   friend class ArcIterator< ComplementFst<A> >;
112 
113   typedef A Arc;
114   typedef typename A::Label Label;
115   typedef typename A::Weight Weight;
116   typedef typename A::StateId StateId;
117 
ComplementFst(const Fst<A> & fst)118   explicit ComplementFst(const Fst<A> &fst)
119       : impl_(new ComplementFstImpl<A>(fst)) {
120     uint64 props = kUnweighted | kNoEpsilons | kIDeterministic | kAcceptor;
121     if (fst.Properties(props, true) != props)
122       LOG(FATAL) << "ComplementFst: argument not an unweighted"
123                  << " epsilon-free deterministic acceptor";
124   }
125 
ComplementFst(const ComplementFst<A> & fst)126   ComplementFst(const ComplementFst<A> &fst) : impl_(fst.impl_) {
127     impl_->IncrRefCount();
128   }
129 
~ComplementFst()130   virtual ~ComplementFst() { if (!impl_->DecrRefCount()) { delete impl_;  }}
131 
Start()132   virtual StateId Start() const { return impl_->Start(); }
133 
Final(StateId s)134   virtual Weight Final(StateId s) const { return impl_->Final(s); }
135 
Properties(uint64 mask,bool test)136   virtual uint64 Properties(uint64 mask, bool test) const {
137     if (test) {
138       uint64 known, test = TestProperties(*this, mask, &known);
139       impl_->SetProperties(test, known);
140       return test & mask;
141     } else {
142       return impl_->Properties(mask);
143     }
144   }
145 
Type()146   virtual const string& Type() const { return impl_->Type(); }
147 
Copy()148   virtual ComplementFst<A> *Copy() const {
149     return new ComplementFst<A>(*this);
150   }
151 
InputSymbols()152   virtual const SymbolTable* InputSymbols() const {
153     return impl_->InputSymbols();
154   }
155 
OutputSymbols()156   virtual const SymbolTable* OutputSymbols() const {
157     return impl_->OutputSymbols();
158   }
159 
NumArcs(StateId s)160   virtual size_t NumArcs(StateId s) const { return impl_->NumArcs(s); }
161 
NumInputEpsilons(StateId s)162   virtual size_t NumInputEpsilons(StateId s) const {
163     return impl_->NumInputEpsilons(s);
164   }
165 
NumOutputEpsilons(StateId s)166   virtual size_t NumOutputEpsilons(StateId s) const {
167     return impl_->NumOutputEpsilons(s);
168   }
169 
170   virtual inline void InitStateIterator(StateIteratorData<A> *data) const;
171 
172   virtual inline void InitArcIterator(StateId s,
173                                       ArcIteratorData<A> *data) const;
174 
175  private:
176   ComplementFstImpl<A> *impl_;
177 
178   void operator=(const ComplementFst<A> &fst);  // disallow
179 };
180 
181 
182 // Specialization for ComplementFst.
183 template <class A>
184 class StateIterator< ComplementFst<A> > : public StateIteratorBase<A> {
185  public:
186   typedef typename A::StateId StateId;
187   typedef typename A::Label Label;
188 
StateIterator(const ComplementFst<A> & fst)189   explicit StateIterator(const ComplementFst<A> &fst)
190       : siter_(*fst.impl_->fst_), s_(0) {
191   }
192 
Done()193   virtual bool Done() const { return s_ > 0 && siter_.Done(); }
Value()194   virtual StateId Value() const { return s_; }
Next()195   virtual void Next() {
196     if (s_ != 0)
197       siter_.Next();
198     ++s_;
199   }
Reset()200   virtual void Reset() {
201     siter_.Reset();
202     s_ = 0;
203   }
204 
205  private:
206   StateIterator< Fst<A> > siter_;
207   StateId s_;
208 
209   DISALLOW_EVIL_CONSTRUCTORS(StateIterator);
210 };
211 
212 
213 // Specialization for ComplementFst.
214 template <class A>
215 class ArcIterator< ComplementFst<A> > : public ArcIteratorBase<A> {
216  public:
217   typedef typename A::StateId StateId;
218   typedef typename A::Label Label;
219   typedef typename A::Weight Weight;
220 
ArcIterator(const ComplementFst<A> & fst,StateId s)221   ArcIterator(const ComplementFst<A> &fst, StateId s)
222       : aiter_(0), s_(s), pos_(0) {
223     if (s_ != 0)
224       aiter_ = new ArcIterator< Fst<A> >(*fst.impl_->fst_, s - 1);
225   }
~ArcIterator()226   virtual ~ArcIterator() { delete aiter_; }
227 
Done()228   virtual bool Done() const {
229     if (s_ != 0)
230       return pos_ > 0 && aiter_->Done();
231     else
232       return pos_ > 0;
233   }
234 
235   // Adds the rho label to the rho destination state.
Value()236   virtual const A& Value() const {
237     if (pos_ == 0) {
238       arc_.ilabel = arc_.olabel = kRhoLabel;
239       arc_.weight = Weight::One();
240       arc_.nextstate = 0;
241     } else {
242       arc_ = aiter_->Value();
243       ++arc_.nextstate;
244     }
245     return arc_;
246   }
Next()247   virtual void Next() {
248     if (s_ != 0 && pos_ > 0)
249       aiter_->Next();
250     ++pos_;
251   }
Reset()252   virtual void Reset() {
253     if (s_ != 0)
254       aiter_->Reset();
255     pos_ = 0;
256   }
Seek(size_t a)257   virtual void Seek(size_t a) {
258     if (s_ != 0) {
259       if (a == 0) {
260         aiter_->Reset();
261       } else {
262         aiter_->Seek(a - 1);
263       }
264     }
265     pos_ = a;
266   }
267 
268  private:
269   ArcIterator< Fst<A> > *aiter_;
270   StateId s_;
271   size_t pos_;
272   mutable A arc_;
273   DISALLOW_EVIL_CONSTRUCTORS(ArcIterator);
274 };
275 
276 
277 template <class A> inline void
InitStateIterator(StateIteratorData<A> * data)278 ComplementFst<A>::InitStateIterator(StateIteratorData<A> *data) const {
279   data->base = new StateIterator< ComplementFst<A> >(*this);
280 }
281 
282 template <class A> inline void
InitArcIterator(StateId s,ArcIteratorData<A> * data)283 ComplementFst<A>::InitArcIterator(StateId s, ArcIteratorData<A> *data) const {
284   data->base = new ArcIterator< ComplementFst<A> >(*this, s);
285 }
286 
287 
288 // Useful alias when using StdArc.
289 typedef ComplementFst<StdArc> StdComplementFst;
290 
291 }  // namespace fst
292 
293 #endif  // FST_LIB_COMPLEMENT_H__
294