Home | History | Annotate | Download | only in fst
      1 // vector-fst.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 // Simple concrete, mutable FST whose states and arcs are stored in STL
     20 // vectors.
     21 
     22 #ifndef FST_LIB_VECTOR_FST_H__
     23 #define FST_LIB_VECTOR_FST_H__
     24 
     25 #include <string>
     26 #include <vector>
     27 using std::vector;
     28 
     29 #include <fst/mutable-fst.h>
     30 #include <fst/test-properties.h>
     31 
     32 
     33 namespace fst {
     34 
     35 template <class A> class VectorFst;
     36 template <class F, class G> void Cast(const F &, G *);
     37 
     38 
     39 // States and arcs implemented by STL vectors, templated on the
     40 // State definition. This does not manage the Fst properties.
     41 template <class State>
     42 class VectorFstBaseImpl : public FstImpl<typename State::Arc> {
     43  public:
     44   typedef typename State::Arc Arc;
     45   typedef typename Arc::Weight Weight;
     46   typedef typename Arc::StateId StateId;
     47 
     48   VectorFstBaseImpl() : start_(kNoStateId) {}
     49 
     50   ~VectorFstBaseImpl() {
     51     for (StateId s = 0; s < states_.size(); ++s)
     52       delete states_[s];
     53   }
     54 
     55   StateId Start() const { return start_; }
     56 
     57   Weight Final(StateId s) const { return states_[s]->final; }
     58 
     59   StateId NumStates() const { return states_.size(); }
     60 
     61   size_t NumArcs(StateId s) const { return states_[s]->arcs.size(); }
     62 
     63   void SetStart(StateId s) { start_ = s; }
     64 
     65   void SetFinal(StateId s, Weight w) { states_[s]->final = w; }
     66 
     67   StateId AddState() {
     68     states_.push_back(new State);
     69     return states_.size() - 1;
     70   }
     71 
     72   StateId AddState(State *state) {
     73     states_.push_back(state);
     74     return states_.size() - 1;
     75   }
     76 
     77   void AddArc(StateId s, const Arc &arc) {
     78     states_[s]->arcs.push_back(arc);
     79   }
     80 
     81   void DeleteStates(const vector<StateId>& dstates) {
     82     vector<StateId> newid(states_.size(), 0);
     83     for (size_t i = 0; i < dstates.size(); ++i)
     84       newid[dstates[i]] = kNoStateId;
     85     StateId nstates = 0;
     86     for (StateId s = 0; s < states_.size(); ++s) {
     87       if (newid[s] != kNoStateId) {
     88         newid[s] = nstates;
     89         if (s != nstates)
     90           states_[nstates] = states_[s];
     91         ++nstates;
     92       } else {
     93         delete states_[s];
     94       }
     95     }
     96     states_.resize(nstates);
     97     for (StateId s = 0; s < states_.size(); ++s) {
     98       vector<Arc> &arcs = states_[s]->arcs;
     99       size_t narcs = 0;
    100       for (size_t i = 0; i < arcs.size(); ++i) {
    101         StateId t = newid[arcs[i].nextstate];
    102         if (t != kNoStateId) {
    103           arcs[i].nextstate = t;
    104           if (i != narcs)
    105             arcs[narcs] = arcs[i];
    106           ++narcs;
    107         } else {
    108           if (arcs[i].ilabel == 0)
    109             --states_[s]->niepsilons;
    110           if (arcs[i].olabel == 0)
    111             --states_[s]->noepsilons;
    112         }
    113       }
    114       arcs.resize(narcs);
    115     }
    116     if (Start() != kNoStateId)
    117       SetStart(newid[Start()]);
    118   }
    119 
    120   void DeleteStates() {
    121     for (StateId s = 0; s < states_.size(); ++s)
    122       delete states_[s];
    123     states_.clear();
    124     SetStart(kNoStateId);
    125   }
    126 
    127   void DeleteArcs(StateId s, size_t n) {
    128     states_[s]->arcs.resize(states_[s]->arcs.size() - n);
    129   }
    130 
    131   void DeleteArcs(StateId s) { states_[s]->arcs.clear(); }
    132 
    133   State *GetState(StateId s) { return states_[s]; }
    134 
    135   const State *GetState(StateId s) const { return states_[s]; }
    136 
    137   void SetState(StateId s, State *state) { states_[s] = state; }
    138 
    139   void ReserveStates(StateId n) { states_.reserve(n); }
    140 
    141   void ReserveArcs(StateId s, size_t n) { states_[s]->arcs.reserve(n); }
    142 
    143   // Provide information needed for generic state iterator
    144   void InitStateIterator(StateIteratorData<Arc> *data) const {
    145     data->base = 0;
    146     data->nstates = states_.size();
    147   }
    148 
    149   // Provide information needed for generic arc iterator
    150   void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const {
    151     data->base = 0;
    152     data->narcs = states_[s]->arcs.size();
    153     data->arcs = data->narcs > 0 ? &states_[s]->arcs[0] : 0;
    154     data->ref_count = 0;
    155   }
    156 
    157  private:
    158   vector<State *> states_;      // States represenation.
    159   StateId start_;               // initial state
    160 
    161   DISALLOW_COPY_AND_ASSIGN(VectorFstBaseImpl);
    162 };
    163 
    164 // Arcs implemented by an STL vector per state.
    165 template <class A>
    166 struct VectorState {
    167   typedef A Arc;
    168   typedef typename A::Weight Weight;
    169   typedef typename A::StateId StateId;
    170 
    171   VectorState() : final(Weight::Zero()), niepsilons(0), noepsilons(0) {}
    172 
    173   Weight final;              // Final weight
    174   vector<A> arcs;            // Arcs represenation
    175   size_t niepsilons;         // # of input epsilons
    176   size_t noepsilons;         // # of output epsilons
    177 };
    178 
    179 // This is a VectorFstBaseImpl container that holds VectorState's.  It
    180 // manages Fst properties and the # of input and output epsilons.
    181 template <class A>
    182 class VectorFstImpl : public VectorFstBaseImpl< VectorState<A> > {
    183  public:
    184   using FstImpl<A>::SetInputSymbols;
    185   using FstImpl<A>::SetOutputSymbols;
    186   using FstImpl<A>::SetType;
    187   using FstImpl<A>::SetProperties;
    188   using FstImpl<A>::Properties;
    189 
    190   using VectorFstBaseImpl<VectorState<A> >::Start;
    191   using VectorFstBaseImpl<VectorState<A> >::NumStates;
    192   using VectorFstBaseImpl<VectorState<A> >::GetState;
    193   using VectorFstBaseImpl<VectorState<A> >::ReserveArcs;
    194 
    195   friend class MutableArcIterator< VectorFst<A> >;
    196 
    197   typedef VectorFstBaseImpl< VectorState<A> > BaseImpl;
    198   typedef typename A::Weight Weight;
    199   typedef typename A::StateId StateId;
    200 
    201   VectorFstImpl() {
    202     SetType("vector");
    203     SetProperties(kNullProperties | kStaticProperties);
    204   }
    205   explicit VectorFstImpl(const Fst<A> &fst);
    206 
    207   static VectorFstImpl<A> *Read(istream &strm, const FstReadOptions &opts);
    208 
    209   size_t NumInputEpsilons(StateId s) const { return GetState(s)->niepsilons; }
    210 
    211   size_t NumOutputEpsilons(StateId s) const { return GetState(s)->noepsilons; }
    212 
    213   void SetStart(StateId s) {
    214     BaseImpl::SetStart(s);
    215     SetProperties(SetStartProperties(Properties()));
    216   }
    217 
    218   void SetFinal(StateId s, Weight w) {
    219     Weight ow = BaseImpl::Final(s);
    220     BaseImpl::SetFinal(s, w);
    221     SetProperties(SetFinalProperties(Properties(), ow, w));
    222   }
    223 
    224   StateId AddState() {
    225     StateId s = BaseImpl::AddState();
    226     SetProperties(AddStateProperties(Properties()));
    227     return s;
    228   }
    229 
    230   void AddArc(StateId s, const A &arc) {
    231     VectorState<A> *state = GetState(s);
    232     if (arc.ilabel == 0) {
    233       ++state->niepsilons;
    234     }
    235     if (arc.olabel == 0) {
    236       ++state->noepsilons;
    237     }
    238 
    239     const A *parc = state->arcs.empty() ? 0 : &(state->arcs.back());
    240     SetProperties(AddArcProperties(Properties(), s, arc, parc));
    241 
    242     BaseImpl::AddArc(s, arc);
    243   }
    244 
    245   void DeleteStates(const vector<StateId> &dstates) {
    246     BaseImpl::DeleteStates(dstates);
    247     SetProperties(DeleteStatesProperties(Properties()));
    248   }
    249 
    250   void DeleteStates() {
    251     BaseImpl::DeleteStates();
    252     SetProperties(DeleteAllStatesProperties(Properties(),
    253                                             kStaticProperties));
    254   }
    255 
    256   void DeleteArcs(StateId s, size_t n) {
    257     const vector<A> &arcs = GetState(s)->arcs;
    258     for (size_t i = 0; i < n; ++i) {
    259       size_t j = arcs.size() - i - 1;
    260       if (arcs[j].ilabel == 0)
    261         --GetState(s)->niepsilons;
    262       if (arcs[j].olabel == 0)
    263         --GetState(s)->noepsilons;
    264     }
    265     BaseImpl::DeleteArcs(s, n);
    266     SetProperties(DeleteArcsProperties(Properties()));
    267   }
    268 
    269   void DeleteArcs(StateId s) {
    270     GetState(s)->niepsilons = 0;
    271     GetState(s)->noepsilons = 0;
    272     BaseImpl::DeleteArcs(s);
    273     SetProperties(DeleteArcsProperties(Properties()));
    274   }
    275 
    276  private:
    277   // Properties always true of this Fst class
    278   static const uint64 kStaticProperties = kExpanded | kMutable;
    279   // Current file format version
    280   static const int kFileVersion = 2;
    281   // Minimum file format version supported
    282   static const int kMinFileVersion = 1;
    283 
    284   DISALLOW_COPY_AND_ASSIGN(VectorFstImpl);
    285 };
    286 
    287 template <class A> const uint64 VectorFstImpl<A>::kStaticProperties;
    288 template <class A> const int VectorFstImpl<A>::kFileVersion;
    289 template <class A> const int VectorFstImpl<A>::kMinFileVersion;
    290 
    291 
    292 template <class A>
    293 VectorFstImpl<A>::VectorFstImpl(const Fst<A> &fst) {
    294   SetType("vector");
    295   SetInputSymbols(fst.InputSymbols());
    296   SetOutputSymbols(fst.OutputSymbols());
    297   BaseImpl::SetStart(fst.Start());
    298   if (fst.Properties(kExpanded, false))
    299     BaseImpl::ReserveStates(CountStates(fst));
    300 
    301   for (StateIterator< Fst<A> > siter(fst);
    302        !siter.Done();
    303        siter.Next()) {
    304     StateId s = siter.Value();
    305     BaseImpl::AddState();
    306     BaseImpl::SetFinal(s, fst.Final(s));
    307     ReserveArcs(s, fst.NumArcs(s));
    308     for (ArcIterator< Fst<A> > aiter(fst, s);
    309          !aiter.Done();
    310          aiter.Next()) {
    311       const A &arc = aiter.Value();
    312       BaseImpl::AddArc(s, arc);
    313       if (arc.ilabel == 0)
    314         ++GetState(s)->niepsilons;
    315       if (arc.olabel == 0)
    316         ++GetState(s)->noepsilons;
    317     }
    318   }
    319   SetProperties(fst.Properties(kCopyProperties, false) | kStaticProperties);
    320 }
    321 
    322 template <class A>
    323 VectorFstImpl<A> *VectorFstImpl<A>::Read(istream &strm,
    324                                          const FstReadOptions &opts) {
    325   VectorFstImpl<A> *impl = new VectorFstImpl;
    326   FstHeader hdr;
    327   if (!impl->ReadHeader(strm, opts, kMinFileVersion, &hdr)) {
    328     delete impl;
    329     return 0;
    330   }
    331   impl->BaseImpl::SetStart(hdr.Start());
    332   if (hdr.NumStates() != kNoStateId) {
    333     impl->ReserveStates(hdr.NumStates());
    334   }
    335 
    336   StateId s = 0;
    337   for (;hdr.NumStates() == kNoStateId || s < hdr.NumStates(); ++s) {
    338     typename A::Weight final;
    339     if (!final.Read(strm)) break;
    340     impl->BaseImpl::AddState();
    341     VectorState<A> *state = impl->GetState(s);
    342     state->final = final;
    343     int64 narcs;
    344     ReadType(strm, &narcs);
    345     if (!strm) {
    346       LOG(ERROR) << "VectorFst::Read: read failed: " << opts.source;
    347       delete impl;
    348       return 0;
    349     }
    350     impl->ReserveArcs(s, narcs);
    351     for (size_t j = 0; j < narcs; ++j) {
    352       A arc;
    353       ReadType(strm, &arc.ilabel);
    354       ReadType(strm, &arc.olabel);
    355       arc.weight.Read(strm);
    356        ReadType(strm, &arc.nextstate);
    357        if (!strm) {
    358         LOG(ERROR) << "VectorFst::Read: read failed: " << opts.source;
    359         delete impl;
    360         return 0;
    361       }
    362       impl->BaseImpl::AddArc(s, arc);
    363       if (arc.ilabel == 0)
    364         ++state->niepsilons;
    365       if (arc.olabel == 0)
    366         ++state->noepsilons;
    367     }
    368   }
    369   if (hdr.NumStates() != kNoStateId && s != hdr.NumStates()) {
    370     LOG(ERROR) << "VectorFst::Read: unexpected end of file: " << opts.source;
    371     delete impl;
    372     return 0;
    373   }
    374   return impl;
    375 }
    376 
    377 // Converts a string into a weight.
    378 template <class W> class WeightFromString {
    379  public:
    380   W operator()(const string &s);
    381 };
    382 
    383 // Generic case fails.
    384 template <class W> inline
    385 W WeightFromString<W>::operator()(const string &s) {
    386   FSTERROR() << "VectorFst::Read: Obsolete file format";
    387   return W::NoWeight();
    388 }
    389 
    390 // TropicalWeight version.
    391 template <> inline
    392 TropicalWeight WeightFromString<TropicalWeight>::operator()(const string &s) {
    393   float f;
    394   memcpy(&f, s.data(), sizeof(f));
    395   return TropicalWeight(f);
    396 }
    397 
    398 // LogWeight version.
    399 template <> inline
    400 LogWeight WeightFromString<LogWeight>::operator()(const string &s) {
    401   float f;
    402   memcpy(&f, s.data(), sizeof(f));
    403   return LogWeight(f);
    404 }
    405 
    406 // Simple concrete, mutable FST. This class attaches interface to
    407 // implementation and handles reference counting, delegating most
    408 // methods to ImplToMutableFst. Supports additional operations:
    409 // ReserveStates and ReserveArcs (cf. STL vectors).
    410 template <class A>
    411 class VectorFst : public ImplToMutableFst< VectorFstImpl<A> > {
    412  public:
    413   friend class StateIterator< VectorFst<A> >;
    414   friend class ArcIterator< VectorFst<A> >;
    415   friend class MutableArcIterator< VectorFst<A> >;
    416   template <class F, class G> friend void Cast(const F &, G *);
    417 
    418   typedef A Arc;
    419   typedef typename A::StateId StateId;
    420   typedef VectorFstImpl<A> Impl;
    421 
    422   VectorFst() : ImplToMutableFst<Impl>(new Impl) {}
    423 
    424   explicit VectorFst(const Fst<A> &fst)
    425       : ImplToMutableFst<Impl>(new Impl(fst)) {}
    426 
    427   VectorFst(const VectorFst<A> &fst) : ImplToMutableFst<Impl>(fst) {}
    428 
    429   // Get a copy of this VectorFst. See Fst<>::Copy() for further doc.
    430   virtual VectorFst<A> *Copy(bool safe = false) const {
    431     return new VectorFst<A>(*this);
    432   }
    433 
    434   VectorFst<A> &operator=(const VectorFst<A> &fst) {
    435     SetImpl(fst.GetImpl(), false);
    436     return *this;
    437   }
    438 
    439   virtual VectorFst<A> &operator=(const Fst<A> &fst) {
    440     if (this != &fst) SetImpl(new Impl(fst));
    441     return *this;
    442   }
    443 
    444   // Read a VectorFst from an input stream; return NULL on error
    445   static VectorFst<A> *Read(istream &strm, const FstReadOptions &opts) {
    446     Impl* impl = Impl::Read(strm, opts);
    447     return impl ? new VectorFst<A>(impl) : 0;
    448   }
    449 
    450   // Read a VectorFst from a file; return NULL on error
    451   // Empty filename reads from standard input
    452   static VectorFst<A> *Read(const string &filename) {
    453     Impl* impl = ImplToExpandedFst<Impl, MutableFst<A> >::Read(filename);
    454     return impl ? new VectorFst<A>(impl) : 0;
    455   }
    456 
    457   virtual bool Write(ostream &strm, const FstWriteOptions &opts) const {
    458     return WriteFst(*this, strm, opts);
    459   }
    460 
    461   virtual bool Write(const string &filename) const {
    462     return Fst<A>::WriteFile(filename);
    463   }
    464 
    465   template <class F>
    466   static bool WriteFst(const F &fst, ostream &strm,
    467                        const FstWriteOptions &opts);
    468 
    469   void ReserveStates(StateId n) {
    470     MutateCheck();
    471     GetImpl()->ReserveStates(n);
    472   }
    473 
    474   void ReserveArcs(StateId s, size_t n) {
    475     MutateCheck();
    476     GetImpl()->ReserveArcs(s, n);
    477   }
    478 
    479   virtual void InitStateIterator(StateIteratorData<Arc> *data) const {
    480     GetImpl()->InitStateIterator(data);
    481   }
    482 
    483   virtual void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const {
    484     GetImpl()->InitArcIterator(s, data);
    485   }
    486 
    487   virtual inline
    488   void InitMutableArcIterator(StateId s, MutableArcIteratorData<A> *);
    489 
    490  private:
    491   explicit VectorFst(Impl *impl) : ImplToMutableFst<Impl>(impl) {}
    492 
    493   // Makes visible to friends.
    494   Impl *GetImpl() const { return ImplToFst< Impl, MutableFst<A> >::GetImpl(); }
    495 
    496   void SetImpl(Impl *impl, bool own_impl = true) {
    497     ImplToFst< Impl, MutableFst<A> >::SetImpl(impl, own_impl);
    498   }
    499 
    500   void MutateCheck() { return ImplToMutableFst<Impl>::MutateCheck(); }
    501 };
    502 
    503 // Specialization for VectorFst; see generic version in fst.h
    504 // for sample usage (but use the VectorFst type!). This version
    505 // should inline.
    506 template <class A>
    507 class StateIterator< VectorFst<A> > {
    508  public:
    509   typedef typename A::StateId StateId;
    510 
    511   explicit StateIterator(const VectorFst<A> &fst)
    512       : nstates_(fst.GetImpl()->NumStates()), s_(0) {}
    513 
    514   bool Done() const { return s_ >= nstates_; }
    515 
    516   StateId Value() const { return s_; }
    517 
    518   void Next() { ++s_; }
    519 
    520   void Reset() { s_ = 0; }
    521 
    522  private:
    523   StateId nstates_;
    524   StateId s_;
    525 
    526   DISALLOW_COPY_AND_ASSIGN(StateIterator);
    527 };
    528 
    529 // Writes Fst to file, will call CountStates so may involve two passes if
    530 // called from an Fst that is not derived from Expanded.
    531 template <class A>
    532 template <class F>
    533 bool VectorFst<A>::WriteFst(const F &fst, ostream &strm,
    534                             const FstWriteOptions &opts) {
    535   static const int kFileVersion = 2;
    536   bool update_header = true;
    537   FstHeader hdr;
    538   hdr.SetStart(fst.Start());
    539   hdr.SetNumStates(kNoStateId);
    540   size_t start_offset = 0;
    541   if (fst.Properties(kExpanded, false) || (start_offset = strm.tellp()) != -1) {
    542     hdr.SetNumStates(CountStates(fst));
    543     update_header = false;
    544   }
    545   FstImpl<A>::WriteFstHeader(fst, strm, opts, kFileVersion, "vector", &hdr);
    546   StateId num_states = 0;
    547   for (StateIterator<F> siter(fst); !siter.Done(); siter.Next()) {
    548     typename A::StateId s = siter.Value();
    549     fst.Final(s).Write(strm);
    550     int64 narcs = fst.NumArcs(s);
    551     WriteType(strm, narcs);
    552     for (ArcIterator<F> aiter(fst, s); !aiter.Done(); aiter.Next()) {
    553       const A &arc = aiter.Value();
    554       WriteType(strm, arc.ilabel);
    555       WriteType(strm, arc.olabel);
    556       arc.weight.Write(strm);
    557       WriteType(strm, arc.nextstate);
    558     }
    559     num_states++;
    560   }
    561   strm.flush();
    562   if (!strm) {
    563     LOG(ERROR) << "VectorFst::Write: write failed: " << opts.source;
    564     return false;
    565   }
    566   if (update_header) {
    567     hdr.SetNumStates(num_states);
    568     return FstImpl<A>::UpdateFstHeader(fst, strm, opts, kFileVersion, "vector",
    569                                        &hdr, start_offset);
    570   } else {
    571     if (num_states != hdr.NumStates()) {
    572       LOG(ERROR) << "Inconsistent number of states observed during write";
    573       return false;
    574     }
    575   }
    576   return true;
    577 }
    578 
    579 // Specialization for VectorFst; see generic version in fst.h
    580 // for sample usage (but use the VectorFst type!). This version
    581 // should inline.
    582 template <class A>
    583 class ArcIterator< VectorFst<A> > {
    584  public:
    585   typedef typename A::StateId StateId;
    586 
    587   ArcIterator(const VectorFst<A> &fst, StateId s)
    588       : arcs_(fst.GetImpl()->GetState(s)->arcs), i_(0) {}
    589 
    590   bool Done() const { return i_ >= arcs_.size(); }
    591 
    592   const A& Value() const { return arcs_[i_]; }
    593 
    594   void Next() { ++i_; }
    595 
    596   void Reset() { i_ = 0; }
    597 
    598   void Seek(size_t a) { i_ = a; }
    599 
    600   size_t Position() const { return i_; }
    601 
    602   uint32 Flags() const {
    603     return kArcValueFlags;
    604   }
    605 
    606   void SetFlags(uint32 f, uint32 m) {}
    607 
    608  private:
    609   const vector<A>& arcs_;
    610   size_t i_;
    611 
    612   DISALLOW_COPY_AND_ASSIGN(ArcIterator);
    613 };
    614 
    615 // Specialization for VectorFst; see generic version in fst.h
    616 // for sample usage (but use the VectorFst type!). This version
    617 // should inline.
    618 template <class A>
    619 class MutableArcIterator< VectorFst<A> >
    620   : public MutableArcIteratorBase<A> {
    621  public:
    622   typedef typename A::StateId StateId;
    623   typedef typename A::Weight Weight;
    624 
    625   MutableArcIterator(VectorFst<A> *fst, StateId s) : i_(0) {
    626     fst->MutateCheck();
    627     state_ = fst->GetImpl()->GetState(s);
    628     properties_ = &fst->GetImpl()->properties_;
    629   }
    630 
    631   bool Done() const { return i_ >= state_->arcs.size(); }
    632 
    633   const A& Value() const { return state_->arcs[i_]; }
    634 
    635   void Next() { ++i_; }
    636 
    637   size_t Position() const { return i_; }
    638 
    639   void Reset() { i_ = 0; }
    640 
    641   void Seek(size_t a) { i_ = a; }
    642 
    643   void SetValue(const A &arc) {
    644     A& oarc = state_->arcs[i_];
    645     if (oarc.ilabel != oarc.olabel)
    646       *properties_ &= ~kNotAcceptor;
    647     if (oarc.ilabel == 0) {
    648       --state_->niepsilons;
    649       *properties_ &= ~kIEpsilons;
    650       if (oarc.olabel == 0)
    651         *properties_ &= ~kEpsilons;
    652     }
    653     if (oarc.olabel == 0) {
    654       --state_->noepsilons;
    655       *properties_ &= ~kOEpsilons;
    656     }
    657     if (oarc.weight != Weight::Zero() && oarc.weight != Weight::One())
    658       *properties_ &= ~kWeighted;
    659     oarc = arc;
    660     if (arc.ilabel != arc.olabel) {
    661       *properties_ |= kNotAcceptor;
    662       *properties_ &= ~kAcceptor;
    663     }
    664     if (arc.ilabel == 0) {
    665       ++state_->niepsilons;
    666       *properties_ |= kIEpsilons;
    667       *properties_ &= ~kNoIEpsilons;
    668       if (arc.olabel == 0) {
    669         *properties_ |= kEpsilons;
    670         *properties_ &= ~kNoEpsilons;
    671       }
    672     }
    673     if (arc.olabel == 0) {
    674       ++state_->noepsilons;
    675       *properties_ |= kOEpsilons;
    676       *properties_ &= ~kNoOEpsilons;
    677     }
    678     if (arc.weight != Weight::Zero() && arc.weight != Weight::One()) {
    679       *properties_ |= kWeighted;
    680       *properties_ &= ~kUnweighted;
    681     }
    682     *properties_ &= kSetArcProperties | kAcceptor | kNotAcceptor |
    683         kEpsilons | kNoEpsilons | kIEpsilons | kNoIEpsilons |
    684         kOEpsilons | kNoOEpsilons | kWeighted | kUnweighted;
    685   }
    686 
    687   uint32 Flags() const {
    688     return kArcValueFlags;
    689   }
    690 
    691   void SetFlags(uint32 f, uint32 m) {}
    692 
    693 
    694  private:
    695   // This allows base-class virtual access to non-virtual derived-
    696   // class members of the same name. It makes the derived class more
    697   // efficient to use but unsafe to further derive.
    698   virtual bool Done_() const { return Done(); }
    699   virtual const A& Value_() const { return Value(); }
    700   virtual void Next_() { Next(); }
    701   virtual size_t Position_() const { return Position(); }
    702   virtual void Reset_() { Reset(); }
    703   virtual void Seek_(size_t a) { Seek(a); }
    704   virtual void SetValue_(const A &a) { SetValue(a); }
    705   uint32 Flags_() const { return Flags(); }
    706   void SetFlags_(uint32 f, uint32 m) { SetFlags(f, m); }
    707 
    708   struct VectorState<A> *state_;
    709   uint64 *properties_;
    710   size_t i_;
    711 
    712   DISALLOW_COPY_AND_ASSIGN(MutableArcIterator);
    713 };
    714 
    715 // Provide information needed for the generic mutable arc iterator
    716 template <class A> inline
    717 void VectorFst<A>::InitMutableArcIterator(
    718     StateId s, MutableArcIteratorData<A> *data) {
    719   data->base = new MutableArcIterator< VectorFst<A> >(this, s);
    720 }
    721 
    722 // A useful alias when using StdArc.
    723 typedef VectorFst<StdArc> StdVectorFst;
    724 
    725 }  // namespace fst
    726 
    727 #endif  // FST_LIB_VECTOR_FST_H__
    728