Home | History | Annotate | Download | only in fst
      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 // Copyright 2005-2010 Google, Inc.
     16 // Author: riley (at) google.com (Michael Riley)
     17 //
     18 // \file
     19 // Class to complement an Fst.
     20 
     21 #ifndef FST_LIB_COMPLEMENT_H__
     22 #define FST_LIB_COMPLEMENT_H__
     23 
     24 #include <algorithm>
     25 #include <string>
     26 #include <vector>
     27 using std::vector;
     28 
     29 #include <fst/fst.h>
     30 #include <fst/test-properties.h>
     31 
     32 
     33 namespace fst {
     34 
     35 template <class A> class ComplementFst;
     36 
     37 // Implementation of delayed ComplementFst. The algorithm used
     38 // completes the (deterministic) FSA and then exchanges final and
     39 // non-final states.  Completion, i.e. ensuring that all labels can be
     40 // read from every state, is accomplished by using RHO labels, which
     41 // match all labels that are otherwise not found leaving a state. The
     42 // first state in the output is reserved to be a new state that is the
     43 // destination of all RHO labels. Each remaining output state s
     44 // corresponds to input state s - 1. The first arc in the output at
     45 // these states is the rho label, the remaining arcs correspond to the
     46 // input arcs.
     47 template <class A>
     48 class ComplementFstImpl : public FstImpl<A> {
     49  public:
     50   using FstImpl<A>::SetType;
     51   using FstImpl<A>::SetProperties;
     52   using FstImpl<A>::SetInputSymbols;
     53   using FstImpl<A>::SetOutputSymbols;
     54 
     55   friend class StateIterator< ComplementFst<A> >;
     56   friend class ArcIterator< ComplementFst<A> >;
     57 
     58   typedef A Arc;
     59   typedef typename A::Label Label;
     60   typedef typename A::Weight Weight;
     61   typedef typename A::StateId StateId;
     62 
     63   explicit ComplementFstImpl(const Fst<A> &fst) : fst_(fst.Copy()) {
     64     SetType("complement");
     65     uint64 props = fst.Properties(kILabelSorted, false);
     66     SetProperties(ComplementProperties(props), kCopyProperties);
     67     SetInputSymbols(fst.InputSymbols());
     68     SetOutputSymbols(fst.OutputSymbols());
     69   }
     70 
     71   ComplementFstImpl(const ComplementFstImpl<A> &impl)
     72       : fst_(impl.fst_->Copy()) {
     73     SetType("complement");
     74     SetProperties(impl.Properties(), kCopyProperties);
     75     SetInputSymbols(impl.InputSymbols());
     76     SetOutputSymbols(impl.OutputSymbols());
     77   }
     78 
     79   ~ComplementFstImpl() { delete fst_; }
     80 
     81   StateId Start() const {
     82     if (Properties(kError))
     83       return kNoStateId;
     84 
     85     StateId start = fst_->Start();
     86     if (start != kNoStateId)
     87       return start + 1;
     88     else
     89       return 0;
     90   }
     91 
     92   // Exchange final and non-final states; make rho destination state final.
     93   Weight Final(StateId s) const {
     94     if (s == 0 || fst_->Final(s - 1) == Weight::Zero())
     95       return Weight::One();
     96     else
     97       return Weight::Zero();
     98   }
     99 
    100   size_t NumArcs(StateId s) const {
    101     if (s == 0)
    102       return 1;
    103     else
    104       return fst_->NumArcs(s - 1) + 1;
    105   }
    106 
    107   size_t NumInputEpsilons(StateId s) const {
    108     return s == 0 ? 0 : fst_->NumInputEpsilons(s - 1);
    109   }
    110 
    111   size_t NumOutputEpsilons(StateId s) const {
    112     return s == 0 ? 0 : fst_->NumOutputEpsilons(s - 1);
    113   }
    114 
    115 
    116   uint64 Properties() const { return Properties(kFstProperties); }
    117 
    118   // Set error if found; return FST impl properties.
    119   uint64 Properties(uint64 mask) const {
    120     if ((mask & kError) && fst_->Properties(kError, false))
    121       SetProperties(kError, kError);
    122     return FstImpl<Arc>::Properties(mask);
    123   }
    124 
    125 
    126  private:
    127   const Fst<A> *fst_;
    128 
    129   void operator=(const ComplementFstImpl<A> &fst);  // Disallow
    130 };
    131 
    132 
    133 // Complements an automaton. This is a library-internal operation that
    134 // introduces a (negative) 'rho' label; use Difference/DifferenceFst in
    135 // user code, which will not see this label. This version is a delayed Fst.
    136 //
    137 // This class attaches interface to implementation and handles
    138 // reference counting, delegating most methods to ImplToFst.
    139 template <class A>
    140 class ComplementFst : public ImplToFst< ComplementFstImpl<A> > {
    141  public:
    142   friend class StateIterator< ComplementFst<A> >;
    143   friend class ArcIterator< ComplementFst<A> >;
    144 
    145   using ImplToFst< ComplementFstImpl<A> >::GetImpl;
    146 
    147   typedef A Arc;
    148   typedef typename A::StateId StateId;
    149   typedef typename A::Label Label;
    150   typedef ComplementFstImpl<A> Impl;
    151 
    152   explicit ComplementFst(const Fst<A> &fst)
    153       : ImplToFst<Impl>(new Impl(fst)) {
    154     uint64 props = kUnweighted | kNoEpsilons | kIDeterministic | kAcceptor;
    155     if (fst.Properties(props, true) != props) {
    156       FSTERROR() << "ComplementFst: argument not an unweighted "
    157                  << "epsilon-free deterministic acceptor";
    158       GetImpl()->SetProperties(kError, kError);
    159     }
    160   }
    161 
    162   // See Fst<>::Copy() for doc.
    163   ComplementFst(const ComplementFst<A> &fst, bool safe = false)
    164       : ImplToFst<Impl>(fst, safe) {}
    165 
    166   // Get a copy of this ComplementFst. See Fst<>::Copy() for further doc.
    167   virtual ComplementFst<A> *Copy(bool safe = false) const {
    168     return new ComplementFst<A>(*this, safe);
    169   }
    170 
    171   virtual inline void InitStateIterator(StateIteratorData<A> *data) const;
    172 
    173   virtual inline void InitArcIterator(StateId s,
    174                                       ArcIteratorData<A> *data) const;
    175 
    176   // Label that represents the rho transition.
    177   // We use a negative value, which is thus private to the library and
    178   // which will preserve FST label sort order.
    179   static const Label kRhoLabel = -2;
    180  private:
    181   // Makes visible to friends.
    182   Impl *GetImpl() const { return ImplToFst<Impl>::GetImpl(); }
    183 
    184   void operator=(const ComplementFst<A> &fst);  // disallow
    185 };
    186 
    187 template <class A> const typename A::Label ComplementFst<A>::kRhoLabel;
    188 
    189 
    190 // Specialization for ComplementFst.
    191 template <class A>
    192 class StateIterator< ComplementFst<A> > : public StateIteratorBase<A> {
    193  public:
    194   typedef typename A::StateId StateId;
    195   typedef typename A::Label Label;
    196 
    197   explicit StateIterator(const ComplementFst<A> &fst)
    198       : siter_(*fst.GetImpl()->fst_), s_(0) {
    199   }
    200 
    201   bool Done() const { return s_ > 0 && siter_.Done(); }
    202 
    203   StateId Value() const { return s_; }
    204 
    205   void Next() {
    206     if (s_ != 0)
    207       siter_.Next();
    208     ++s_;
    209   }
    210 
    211   void Reset() {
    212     siter_.Reset();
    213     s_ = 0;
    214   }
    215 
    216  private:
    217   // This allows base class virtual access to non-virtual derived-
    218   // class members of the same name. It makes the derived class more
    219   // efficient to use but unsafe to further derive.
    220   virtual bool Done_() const { return Done(); }
    221   virtual StateId Value_() const { return Value(); }
    222   virtual void Next_() { Next(); }
    223   virtual void Reset_() { Reset(); }
    224 
    225   StateIterator< Fst<A> > siter_;
    226   StateId s_;
    227 
    228   DISALLOW_COPY_AND_ASSIGN(StateIterator);
    229 };
    230 
    231 
    232 // Specialization for ComplementFst.
    233 template <class A>
    234 class ArcIterator< ComplementFst<A> > : public ArcIteratorBase<A> {
    235  public:
    236   typedef typename A::StateId StateId;
    237   typedef typename A::Label Label;
    238   typedef typename A::Weight Weight;
    239 
    240   ArcIterator(const ComplementFst<A> &fst, StateId s)
    241       : aiter_(0), s_(s), pos_(0) {
    242     if (s_ != 0)
    243       aiter_ = new ArcIterator< Fst<A> >(*fst.GetImpl()->fst_, s - 1);
    244   }
    245 
    246   virtual ~ArcIterator() { delete aiter_; }
    247 
    248   bool Done() const {
    249     if (s_ != 0)
    250       return pos_ > 0 && aiter_->Done();
    251     else
    252       return pos_ > 0;
    253   }
    254 
    255   // Adds the rho label to the rho destination state.
    256   const A& Value() const {
    257     if (pos_ == 0) {
    258       arc_.ilabel = arc_.olabel = ComplementFst<A>::kRhoLabel;
    259       arc_.weight = Weight::One();
    260       arc_.nextstate = 0;
    261     } else {
    262       arc_ = aiter_->Value();
    263       ++arc_.nextstate;
    264     }
    265     return arc_;
    266   }
    267 
    268   void Next() {
    269     if (s_ != 0 && pos_ > 0)
    270       aiter_->Next();
    271     ++pos_;
    272   }
    273 
    274   size_t Position() const {
    275     return pos_;
    276   }
    277 
    278   void Reset() {
    279     if (s_ != 0)
    280       aiter_->Reset();
    281     pos_ = 0;
    282   }
    283 
    284   void Seek(size_t a) {
    285     if (s_ != 0) {
    286       if (a == 0) {
    287         aiter_->Reset();
    288       } else {
    289         aiter_->Seek(a - 1);
    290       }
    291     }
    292     pos_ = a;
    293   }
    294 
    295   uint32 Flags() const {
    296     return kArcValueFlags;
    297   }
    298 
    299   void SetFlags(uint32 f, uint32 m) {}
    300 
    301  private:
    302   // This allows base class virtual access to non-virtual derived-
    303   // class members of the same name. It makes the derived class more
    304   // efficient to use but unsafe to further derive.
    305   virtual bool Done_() const { return Done(); }
    306   virtual const A& Value_() const { return Value(); }
    307   virtual void Next_() { Next(); }
    308   virtual size_t Position_() const { return Position(); }
    309   virtual void Reset_() { Reset(); }
    310   virtual void Seek_(size_t a) { Seek(a); }
    311   uint32 Flags_() const { return Flags(); }
    312   void SetFlags_(uint32 f, uint32 m) { SetFlags(f, m); }
    313 
    314   ArcIterator< Fst<A> > *aiter_;
    315   StateId s_;
    316   size_t pos_;
    317   mutable A arc_;
    318   DISALLOW_COPY_AND_ASSIGN(ArcIterator);
    319 };
    320 
    321 
    322 template <class A> inline void
    323 ComplementFst<A>::InitStateIterator(StateIteratorData<A> *data) const {
    324   data->base = new StateIterator< ComplementFst<A> >(*this);
    325 }
    326 
    327 template <class A> inline void
    328 ComplementFst<A>::InitArcIterator(StateId s, ArcIteratorData<A> *data) const {
    329   data->base = new ArcIterator< ComplementFst<A> >(*this, s);
    330 }
    331 
    332 
    333 // Useful alias when using StdArc.
    334 typedef ComplementFst<StdArc> StdComplementFst;
    335 
    336 }  // namespace fst
    337 
    338 #endif  // FST_LIB_COMPLEMENT_H__
    339