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 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 65 ~ComplementFstImpl() { delete fst_; } 66 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. 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 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 90 size_t NumInputEpsilons(StateId s) const { 91 return s == 0 ? 0 : fst_->NumInputEpsilons(s - 1); 92 } 93 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 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 126 ComplementFst(const ComplementFst<A> &fst) : impl_(fst.impl_) { 127 impl_->IncrRefCount(); 128 } 129 130 virtual ~ComplementFst() { if (!impl_->DecrRefCount()) { delete impl_; }} 131 132 virtual StateId Start() const { return impl_->Start(); } 133 134 virtual Weight Final(StateId s) const { return impl_->Final(s); } 135 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 146 virtual const string& Type() const { return impl_->Type(); } 147 148 virtual ComplementFst<A> *Copy() const { 149 return new ComplementFst<A>(*this); 150 } 151 152 virtual const SymbolTable* InputSymbols() const { 153 return impl_->InputSymbols(); 154 } 155 156 virtual const SymbolTable* OutputSymbols() const { 157 return impl_->OutputSymbols(); 158 } 159 160 virtual size_t NumArcs(StateId s) const { return impl_->NumArcs(s); } 161 162 virtual size_t NumInputEpsilons(StateId s) const { 163 return impl_->NumInputEpsilons(s); 164 } 165 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 189 explicit StateIterator(const ComplementFst<A> &fst) 190 : siter_(*fst.impl_->fst_), s_(0) { 191 } 192 193 virtual bool Done() const { return s_ > 0 && siter_.Done(); } 194 virtual StateId Value() const { return s_; } 195 virtual void Next() { 196 if (s_ != 0) 197 siter_.Next(); 198 ++s_; 199 } 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 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 } 226 virtual ~ArcIterator() { delete aiter_; } 227 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. 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 } 247 virtual void Next() { 248 if (s_ != 0 && pos_ > 0) 249 aiter_->Next(); 250 ++pos_; 251 } 252 virtual void Reset() { 253 if (s_ != 0) 254 aiter_->Reset(); 255 pos_ = 0; 256 } 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 278 ComplementFst<A>::InitStateIterator(StateIteratorData<A> *data) const { 279 data->base = new StateIterator< ComplementFst<A> >(*this); 280 } 281 282 template <class A> inline void 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