// lookahead-matcher.h

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright 2005-2010 Google, Inc.
// Author: riley@google.com (Michael Riley)
//
// \file
// Classes to add lookahead to FST matchers, useful e.g. for improving
// composition efficiency with certain inputs.

#ifndef FST_LIB_LOOKAHEAD_MATCHER_H__
#define FST_LIB_LOOKAHEAD_MATCHER_H__

#include <fst/add-on.h>
#include <fst/const-fst.h>
#include <fst/fst.h>
#include <fst/label-reachable.h>
#include <fst/matcher.h>


DECLARE_string(save_relabel_ipairs);
DECLARE_string(save_relabel_opairs);

namespace fst {

// LOOKAHEAD MATCHERS - these have the interface of Matchers (see
// matcher.h) and these additional methods:
//
// template <class F>
// class LookAheadMatcher {
//  public:
//   typedef F FST;
//   typedef F::Arc Arc;
//   typedef typename Arc::StateId StateId;
//   typedef typename Arc::Label Label;
//   typedef typename Arc::Weight Weight;
//
//  // Required constructors.
//  LookAheadMatcher(const F &fst, MatchType match_type);
//   // If safe=true, the copy is thread-safe (except the lookahead Fst is
//   // preserved). See Fst<>::Cop() for further doc.
//  LookAheadMatcher(const LookAheadMatcher &matcher, bool safe = false);
//
//  Below are methods for looking ahead for a match to a label and
//  more generally, to a rational set. Each returns false if there is
//  definitely not a match and returns true if there possibly is a
//  match.

//  // LABEL LOOKAHEAD: Can 'label' be read from the current matcher state
//  // after possibly following epsilon transitions?
//  bool LookAheadLabel(Label label) const;
//
//  // RATIONAL LOOKAHEAD: The next methods allow looking ahead for an
//  // arbitrary rational set of strings, specified by an FST and a state
//  // from which to begin the matching. If the lookahead FST is a
//  // transducer, this looks on the side different from the matcher
//  // 'match_type' (cf. composition).
//
//  // Are there paths P from 's' in the lookahead FST that can be read from
//  // the cur. matcher state?
//  bool LookAheadFst(const Fst<Arc>& fst, StateId s);
//
//  // Gives an estimate of the combined weight of the paths P in the
//  // lookahead and matcher FSTs for the last call to LookAheadFst.
//  // A trivial implementation returns Weight::One(). Non-trivial
//  // implementations are useful for weight-pushing in composition.
//  Weight LookAheadWeight() const;
//
//  // Is there is a single non-epsilon arc found in the lookahead FST
//  // that begins P (after possibly following any epsilons) in the last
//  // call LookAheadFst? If so, return true and copy it to '*arc', o.w.
//  // return false. A trivial implementation returns false. Non-trivial
//  // implementations are useful for label-pushing in composition.
//  bool LookAheadPrefix(Arc *arc);
//
//  // Optionally pre-specifies the lookahead FST that will be passed
//  // to LookAheadFst() for possible precomputation. If copy is true,
//  // then 'fst' is a copy of the FST used in the previous call to
//  // this method (useful to avoid unnecessary updates).
//  void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false);
//
// };

//
// LOOK-AHEAD FLAGS (see also kMatcherFlags in matcher.h):
//
// Matcher is a lookahead matcher when 'match_type' is MATCH_INPUT.
const uint32 kInputLookAheadMatcher =     0x00000010;

// Matcher is a lookahead matcher when 'match_type' is MATCH_OUTPUT.
const uint32 kOutputLookAheadMatcher =    0x00000020;

// A non-trivial implementation of LookAheadWeight() method defined and
// should be used?
const uint32 kLookAheadWeight =           0x00000040;

// A non-trivial implementation of LookAheadPrefix() method defined and
// should be used?
const uint32 kLookAheadPrefix =           0x00000080;

// Look-ahead of matcher FST non-epsilon arcs?
const uint32 kLookAheadNonEpsilons =      0x00000100;

// Look-ahead of matcher FST epsilon arcs?
const uint32 kLookAheadEpsilons =         0x00000200;

// Ignore epsilon paths for the lookahead prefix? Note this gives
// correct results in composition only with an appropriate composition
// filter since it depends on the filter blocking the ignored paths.
const uint32 kLookAheadNonEpsilonPrefix = 0x00000400;

// For LabelLookAheadMatcher, save relabeling data to file
const uint32 kLookAheadKeepRelabelData =  0x00000800;

// Flags used for lookahead matchers.
const uint32 kLookAheadFlags =            0x00000ff0;

// LookAhead Matcher interface, templated on the Arc definition; used
// for lookahead matcher specializations that are returned by the
// InitMatcher() Fst method.
template <class A>
class LookAheadMatcherBase : public MatcherBase<A> {
 public:
  typedef A Arc;
  typedef typename A::StateId StateId;
  typedef typename A::Label Label;
  typedef typename A::Weight Weight;

  LookAheadMatcherBase()
  : weight_(Weight::One()),
    prefix_arc_(kNoLabel, kNoLabel, Weight::One(), kNoStateId) {}

  virtual ~LookAheadMatcherBase() {}

  bool LookAheadLabel(Label label) const { return LookAheadLabel_(label); }

  bool LookAheadFst(const Fst<Arc> &fst, StateId s) {
    return LookAheadFst_(fst, s);
  }

  Weight LookAheadWeight() const { return weight_; }

  bool LookAheadPrefix(Arc *arc) const {
    if (prefix_arc_.nextstate != kNoStateId) {
      *arc = prefix_arc_;
      return true;
    } else {
      return false;
    }
  }

  virtual void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false) = 0;

 protected:
  void SetLookAheadWeight(const Weight &w) { weight_ = w; }

  void SetLookAheadPrefix(const Arc &arc) { prefix_arc_ = arc; }

  void ClearLookAheadPrefix() { prefix_arc_.nextstate = kNoStateId; }

 private:
  virtual bool LookAheadLabel_(Label label) const = 0;
  virtual bool LookAheadFst_(const Fst<Arc> &fst,
                             StateId s) = 0;  // This must set l.a. weight and
                                              // prefix if non-trivial.
  Weight weight_;                             // Look-ahead weight
  Arc prefix_arc_;                            // Look-ahead prefix arc
};


// Don't really lookahead, just declare future looks good regardless.
template <class M>
class TrivialLookAheadMatcher
    : public LookAheadMatcherBase<typename M::FST::Arc> {
 public:
  typedef typename M::FST FST;
  typedef typename M::Arc Arc;
  typedef typename Arc::StateId StateId;
  typedef typename Arc::Label Label;
  typedef typename Arc::Weight Weight;

  TrivialLookAheadMatcher(const FST &fst, MatchType match_type)
      : matcher_(fst, match_type) {}

  TrivialLookAheadMatcher(const TrivialLookAheadMatcher<M> &lmatcher,
                          bool safe = false)
      : matcher_(lmatcher.matcher_, safe) {}

  // General matcher methods
  TrivialLookAheadMatcher<M> *Copy(bool safe = false) const {
    return new TrivialLookAheadMatcher<M>(*this, safe);
  }

  MatchType Type(bool test) const { return matcher_.Type(test); }
  void SetState(StateId s) { return matcher_.SetState(s); }
  bool Find(Label label) { return matcher_.Find(label); }
  bool Done() const { return matcher_.Done(); }
  const Arc& Value() const { return matcher_.Value(); }
  void Next() { matcher_.Next(); }
  virtual const FST &GetFst() const { return matcher_.GetFst(); }
  uint64 Properties(uint64 props) const { return matcher_.Properties(props); }
  uint32 Flags() const {
    return matcher_.Flags() | kInputLookAheadMatcher | kOutputLookAheadMatcher;
  }

  // Look-ahead methods.
  bool LookAheadLabel(Label label) const { return true;  }
  bool LookAheadFst(const Fst<Arc> &fst, StateId s) {return true; }
  Weight LookAheadWeight() const { return Weight::One(); }
  bool LookAheadPrefix(Arc *arc) const { return false; }
  void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false) {}

 private:
  // This allows base class virtual access to non-virtual derived-
  // class members of the same name. It makes the derived class more
  // efficient to use but unsafe to further derive.
  virtual void SetState_(StateId s) { SetState(s); }
  virtual bool Find_(Label label) { return Find(label); }
  virtual bool Done_() const { return Done(); }
  virtual const Arc& Value_() const { return Value(); }
  virtual void Next_() { Next(); }

  bool LookAheadLabel_(Label l) const { return LookAheadLabel(l); }

  bool LookAheadFst_(const Fst<Arc> &fst, StateId s) {
    return LookAheadFst(fst, s);
  }

  Weight LookAheadWeight_() const { return LookAheadWeight(); }
  bool LookAheadPrefix_(Arc *arc) const { return LookAheadPrefix(arc); }

  M matcher_;
};

// Look-ahead of one transition. Template argument F accepts flags to
// control behavior.
template <class M, uint32 F = kLookAheadNonEpsilons | kLookAheadEpsilons |
          kLookAheadWeight | kLookAheadPrefix>
class ArcLookAheadMatcher
    : public LookAheadMatcherBase<typename M::FST::Arc> {
 public:
  typedef typename M::FST FST;
  typedef typename M::Arc Arc;
  typedef typename Arc::StateId StateId;
  typedef typename Arc::Label Label;
  typedef typename Arc::Weight Weight;
  typedef NullAddOn MatcherData;

  using LookAheadMatcherBase<Arc>::LookAheadWeight;
  using LookAheadMatcherBase<Arc>::SetLookAheadPrefix;
  using LookAheadMatcherBase<Arc>::SetLookAheadWeight;
  using LookAheadMatcherBase<Arc>::ClearLookAheadPrefix;

  ArcLookAheadMatcher(const FST &fst, MatchType match_type,
                      MatcherData *data = 0)
      : matcher_(fst, match_type),
        fst_(matcher_.GetFst()),
        lfst_(0),
        s_(kNoStateId) {}

  ArcLookAheadMatcher(const ArcLookAheadMatcher<M, F> &lmatcher,
                      bool safe = false)
      : matcher_(lmatcher.matcher_, safe),
        fst_(matcher_.GetFst()),
        lfst_(lmatcher.lfst_),
        s_(kNoStateId) {}

  // General matcher methods
  ArcLookAheadMatcher<M, F> *Copy(bool safe = false) const {
    return new ArcLookAheadMatcher<M, F>(*this, safe);
  }

  MatchType Type(bool test) const { return matcher_.Type(test); }

  void SetState(StateId s) {
    s_ = s;
    matcher_.SetState(s);
  }

  bool Find(Label label) { return matcher_.Find(label); }
  bool Done() const { return matcher_.Done(); }
  const Arc& Value() const { return matcher_.Value(); }
  void Next() { matcher_.Next(); }
  const FST &GetFst() const { return fst_; }
  uint64 Properties(uint64 props) const { return matcher_.Properties(props); }
  uint32 Flags() const {
    return matcher_.Flags() | kInputLookAheadMatcher |
        kOutputLookAheadMatcher | F;
  }

  // Writable matcher methods
  MatcherData *GetData() const { return 0; }

  // Look-ahead methods.
  bool LookAheadLabel(Label label) const { return matcher_.Find(label); }

  // Checks if there is a matching (possibly super-final) transition
  // at (s_, s).
  bool LookAheadFst(const Fst<Arc> &fst, StateId s);

  void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false) {
    lfst_ = &fst;
  }

 private:
  // This allows base class virtual access to non-virtual derived-
  // class members of the same name. It makes the derived class more
  // efficient to use but unsafe to further derive.
  virtual void SetState_(StateId s) { SetState(s); }
  virtual bool Find_(Label label) { return Find(label); }
  virtual bool Done_() const { return Done(); }
  virtual const Arc& Value_() const { return Value(); }
  virtual void Next_() { Next(); }

  bool LookAheadLabel_(Label l) const { return LookAheadLabel(l); }
  bool LookAheadFst_(const Fst<Arc> &fst, StateId s) {
    return LookAheadFst(fst, s);
  }

  mutable M matcher_;
  const FST &fst_;         // Matcher FST
  const Fst<Arc> *lfst_;   // Look-ahead FST
  StateId s_;              // Matcher state
};

template <class M, uint32 F>
bool ArcLookAheadMatcher<M, F>::LookAheadFst(const Fst<Arc> &fst, StateId s) {
  if (&fst != lfst_)
    InitLookAheadFst(fst);

  bool ret = false;
  ssize_t nprefix = 0;
  if (F & kLookAheadWeight)
    SetLookAheadWeight(Weight::Zero());
  if (F & kLookAheadPrefix)
    ClearLookAheadPrefix();
  if (fst_.Final(s_) != Weight::Zero() &&
      lfst_->Final(s) != Weight::Zero()) {
    if (!(F & (kLookAheadWeight | kLookAheadPrefix)))
      return true;
    ++nprefix;
    if (F & kLookAheadWeight)
      SetLookAheadWeight(Plus(LookAheadWeight(),
                              Times(fst_.Final(s_), lfst_->Final(s))));
    ret = true;
  }
  if (matcher_.Find(kNoLabel)) {
    if (!(F & (kLookAheadWeight | kLookAheadPrefix)))
      return true;
    ++nprefix;
    if (F & kLookAheadWeight)
      for (; !matcher_.Done(); matcher_.Next())
        SetLookAheadWeight(Plus(LookAheadWeight(), matcher_.Value().weight));
    ret = true;
  }
  for (ArcIterator< Fst<Arc> > aiter(*lfst_, s);
       !aiter.Done();
       aiter.Next()) {
    const Arc &arc = aiter.Value();
    Label label = kNoLabel;
    switch (matcher_.Type(false)) {
      case MATCH_INPUT:
        label = arc.olabel;
        break;
      case MATCH_OUTPUT:
        label = arc.ilabel;
        break;
      default:
        FSTERROR() << "ArcLookAheadMatcher::LookAheadFst: bad match type";
        return true;
    }
    if (label == 0) {
      if (!(F & (kLookAheadWeight | kLookAheadPrefix)))
        return true;
      if (!(F & kLookAheadNonEpsilonPrefix))
        ++nprefix;
      if (F & kLookAheadWeight)
        SetLookAheadWeight(Plus(LookAheadWeight(), arc.weight));
      ret = true;
    } else if (matcher_.Find(label)) {
      if (!(F & (kLookAheadWeight | kLookAheadPrefix)))
        return true;
      for (; !matcher_.Done(); matcher_.Next()) {
        ++nprefix;
        if (F & kLookAheadWeight)
          SetLookAheadWeight(Plus(LookAheadWeight(),
                                  Times(arc.weight,
                                        matcher_.Value().weight)));
        if ((F & kLookAheadPrefix) && nprefix == 1)
          SetLookAheadPrefix(arc);
      }
      ret = true;
    }
  }
  if (F & kLookAheadPrefix) {
    if (nprefix == 1)
      SetLookAheadWeight(Weight::One());  // Avoids double counting.
    else
      ClearLookAheadPrefix();
  }
  return ret;
}


// Template argument F accepts flags to control behavior.
// It must include precisely one of KInputLookAheadMatcher or
// KOutputLookAheadMatcher.
template <class M, uint32 F = kLookAheadEpsilons | kLookAheadWeight |
          kLookAheadPrefix | kLookAheadNonEpsilonPrefix |
          kLookAheadKeepRelabelData,
          class S = DefaultAccumulator<typename M::Arc> >
class LabelLookAheadMatcher
    : public LookAheadMatcherBase<typename M::FST::Arc> {
 public:
  typedef typename M::FST FST;
  typedef typename M::Arc Arc;
  typedef typename Arc::StateId StateId;
  typedef typename Arc::Label Label;
  typedef typename Arc::Weight Weight;
  typedef LabelReachableData<Label> MatcherData;

  using LookAheadMatcherBase<Arc>::LookAheadWeight;
  using LookAheadMatcherBase<Arc>::SetLookAheadPrefix;
  using LookAheadMatcherBase<Arc>::SetLookAheadWeight;
  using LookAheadMatcherBase<Arc>::ClearLookAheadPrefix;

  LabelLookAheadMatcher(const FST &fst, MatchType match_type,
                        MatcherData *data = 0, S *s = 0)
      : matcher_(fst, match_type),
        lfst_(0),
        label_reachable_(0),
        s_(kNoStateId),
        error_(false) {
    if (!(F & (kInputLookAheadMatcher | kOutputLookAheadMatcher))) {
      FSTERROR() << "LabelLookaheadMatcher: bad matcher flags: " << F;
      error_ = true;
    }
    bool reach_input = match_type == MATCH_INPUT;
    if (data) {
      if (reach_input == data->ReachInput())
        label_reachable_ = new LabelReachable<Arc, S>(data, s);
    } else if ((reach_input && (F & kInputLookAheadMatcher)) ||
               (!reach_input && (F & kOutputLookAheadMatcher))) {
      label_reachable_ = new LabelReachable<Arc, S>(
          fst, reach_input, s, F & kLookAheadKeepRelabelData);
    }
  }

  LabelLookAheadMatcher(const LabelLookAheadMatcher<M, F, S> &lmatcher,
                        bool safe = false)
      : matcher_(lmatcher.matcher_, safe),
        lfst_(lmatcher.lfst_),
        label_reachable_(
            lmatcher.label_reachable_ ?
            new LabelReachable<Arc, S>(*lmatcher.label_reachable_) : 0),
        s_(kNoStateId),
        error_(lmatcher.error_) {}

  ~LabelLookAheadMatcher() {
    delete label_reachable_;
  }

  // General matcher methods
  LabelLookAheadMatcher<M, F, S> *Copy(bool safe = false) const {
    return new LabelLookAheadMatcher<M, F, S>(*this, safe);
  }

  MatchType Type(bool test) const { return matcher_.Type(test); }

  void SetState(StateId s) {
    if (s_ == s)
      return;
    s_ = s;
    match_set_state_ = false;
    reach_set_state_ = false;
  }

  bool Find(Label label) {
    if (!match_set_state_) {
      matcher_.SetState(s_);
      match_set_state_ = true;
    }
    return matcher_.Find(label);
  }

  bool Done() const { return matcher_.Done(); }
  const Arc& Value() const { return matcher_.Value(); }
  void Next() { matcher_.Next(); }
  const FST &GetFst() const { return matcher_.GetFst(); }

  uint64 Properties(uint64 inprops) const {
    uint64 outprops = matcher_.Properties(inprops);
    if (error_ || (label_reachable_ && label_reachable_->Error()))
      outprops |= kError;
    return outprops;
  }

  uint32 Flags() const {
    if (label_reachable_ && label_reachable_->GetData()->ReachInput())
      return matcher_.Flags() | F | kInputLookAheadMatcher;
    else if (label_reachable_ && !label_reachable_->GetData()->ReachInput())
      return matcher_.Flags() | F | kOutputLookAheadMatcher;
    else
      return matcher_.Flags();
  }

  // Writable matcher methods
  MatcherData *GetData() const {
    return label_reachable_ ? label_reachable_->GetData() : 0;
  };

  // Look-ahead methods.
  bool LookAheadLabel(Label label) const {
    if (label == 0)
      return true;

    if (label_reachable_) {
      if (!reach_set_state_) {
        label_reachable_->SetState(s_);
        reach_set_state_ = true;
      }
      return label_reachable_->Reach(label);
    } else {
      return true;
    }
  }

  // Checks if there is a matching (possibly super-final) transition
  // at (s_, s).
  template <class L>
  bool LookAheadFst(const L &fst, StateId s);

  void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false) {
    lfst_ = &fst;
    if (label_reachable_)
      label_reachable_->ReachInit(fst, copy);
  }

  template <class L>
  void InitLookAheadFst(const L& fst, bool copy = false) {
    lfst_ = static_cast<const Fst<Arc> *>(&fst);
    if (label_reachable_)
      label_reachable_->ReachInit(fst, copy);
  }

 private:
  // This allows base class virtual access to non-virtual derived-
  // class members of the same name. It makes the derived class more
  // efficient to use but unsafe to further derive.
  virtual void SetState_(StateId s) { SetState(s); }
  virtual bool Find_(Label label) { return Find(label); }
  virtual bool Done_() const { return Done(); }
  virtual const Arc& Value_() const { return Value(); }
  virtual void Next_() { Next(); }

  bool LookAheadLabel_(Label l) const { return LookAheadLabel(l); }
  bool LookAheadFst_(const Fst<Arc> &fst, StateId s) {
    return LookAheadFst(fst, s);
  }

  mutable M matcher_;
  const Fst<Arc> *lfst_;                     // Look-ahead FST
  LabelReachable<Arc, S> *label_reachable_;  // Label reachability info
  StateId s_;                                // Matcher state
  bool match_set_state_;                     // matcher_.SetState called?
  mutable bool reach_set_state_;             // reachable_.SetState called?
  bool error_;
};

template <class M, uint32 F, class S>
template <class L> inline
bool LabelLookAheadMatcher<M, F, S>::LookAheadFst(const L &fst, StateId s) {
  if (static_cast<const Fst<Arc> *>(&fst) != lfst_)
    InitLookAheadFst(fst);

  SetLookAheadWeight(Weight::One());
  ClearLookAheadPrefix();

  if (!label_reachable_)
    return true;

  label_reachable_->SetState(s_, s);
  reach_set_state_ = true;

  bool compute_weight = F & kLookAheadWeight;
  bool compute_prefix = F & kLookAheadPrefix;

  bool reach_input = Type(false) == MATCH_OUTPUT;
  ArcIterator<L> aiter(fst, s);
  bool reach_arc = label_reachable_->Reach(&aiter, 0,
                                           internal::NumArcs(*lfst_, s),
                                           reach_input, compute_weight);
  Weight lfinal = internal::Final(*lfst_, s);
  bool reach_final = lfinal != Weight::Zero() && label_reachable_->ReachFinal();
  if (reach_arc) {
    ssize_t begin = label_reachable_->ReachBegin();
    ssize_t end = label_reachable_->ReachEnd();
    if (compute_prefix && end - begin == 1 && !reach_final) {
      aiter.Seek(begin);
      SetLookAheadPrefix(aiter.Value());
      compute_weight = false;
    } else if (compute_weight) {
      SetLookAheadWeight(label_reachable_->ReachWeight());
    }
  }
  if (reach_final && compute_weight)
    SetLookAheadWeight(reach_arc ?
                       Plus(LookAheadWeight(), lfinal) : lfinal);

  return reach_arc || reach_final;
}


// Label-lookahead relabeling class.
template <class A>
class LabelLookAheadRelabeler {
 public:
  typedef typename A::Label Label;
  typedef LabelReachableData<Label> MatcherData;
  typedef AddOnPair<MatcherData, MatcherData> D;

  // Relabels matcher Fst - initialization function object.
  template <typename I>
  LabelLookAheadRelabeler(I **impl);

  // Relabels arbitrary Fst. Class L should be a label-lookahead Fst.
  template <class L>
  static void Relabel(MutableFst<A> *fst, const L &mfst,
                      bool relabel_input) {
    typename L::Impl *impl = mfst.GetImpl();
    D *data = impl->GetAddOn();
    LabelReachable<A> reachable(data->First() ?
                                  data->First() : data->Second());
    reachable.Relabel(fst, relabel_input);
  }

  // Returns relabeling pairs (cf. relabel.h::Relabel()).
  // Class L should be a label-lookahead Fst.
  // If 'avoid_collisions' is true, extra pairs are added to
  // ensure no collisions when relabeling automata that have
  // labels unseen here.
  template <class L>
  static void RelabelPairs(const L &mfst, vector<pair<Label, Label> > *pairs,
                           bool avoid_collisions = false) {
    typename L::Impl *impl = mfst.GetImpl();
    D *data = impl->GetAddOn();
    LabelReachable<A> reachable(data->First() ?
                                  data->First() : data->Second());
    reachable.RelabelPairs(pairs, avoid_collisions);
  }
};

template <class A>
template <typename I> inline
LabelLookAheadRelabeler<A>::LabelLookAheadRelabeler(I **impl) {
  Fst<A> &fst = (*impl)->GetFst();
  D *data = (*impl)->GetAddOn();
  const string name = (*impl)->Type();
  bool is_mutable = fst.Properties(kMutable, false);
  MutableFst<A> *mfst = 0;
  if (is_mutable) {
    mfst = static_cast<MutableFst<A> *>(&fst);
  } else {
    mfst = new VectorFst<A>(fst);
    data->IncrRefCount();
    delete *impl;
  }
  if (data->First()) {  // reach_input
    LabelReachable<A> reachable(data->First());
    reachable.Relabel(mfst, true);
    if (!FLAGS_save_relabel_ipairs.empty()) {
      vector<pair<Label, Label> > pairs;
      reachable.RelabelPairs(&pairs, true);
      WriteLabelPairs(FLAGS_save_relabel_ipairs, pairs);
    }
  } else {
    LabelReachable<A> reachable(data->Second());
    reachable.Relabel(mfst, false);
    if (!FLAGS_save_relabel_opairs.empty()) {
      vector<pair<Label, Label> > pairs;
      reachable.RelabelPairs(&pairs, true);
      WriteLabelPairs(FLAGS_save_relabel_opairs, pairs);
    }
  }
  if (!is_mutable) {
    *impl = new I(*mfst, name);
    (*impl)->SetAddOn(data);
    delete mfst;
    data->DecrRefCount();
  }
}


// Generic lookahead matcher, templated on the FST definition
// - a wrapper around pointer to specific one.
template <class F>
class LookAheadMatcher {
 public:
  typedef F FST;
  typedef typename F::Arc Arc;
  typedef typename Arc::StateId StateId;
  typedef typename Arc::Label Label;
  typedef typename Arc::Weight Weight;
  typedef LookAheadMatcherBase<Arc> LBase;

  LookAheadMatcher(const F &fst, MatchType match_type) {
    base_ = fst.InitMatcher(match_type);
    if (!base_)
      base_ = new SortedMatcher<F>(fst, match_type);
    lookahead_ = false;
  }

  LookAheadMatcher(const LookAheadMatcher<F> &matcher, bool safe = false) {
    base_ = matcher.base_->Copy(safe);
    lookahead_ = matcher.lookahead_;
  }

  ~LookAheadMatcher() { delete base_; }

  // General matcher methods
  LookAheadMatcher<F> *Copy(bool safe = false) const {
      return new LookAheadMatcher<F>(*this, safe);
  }

  MatchType Type(bool test) const { return base_->Type(test); }
  void SetState(StateId s) { base_->SetState(s); }
  bool Find(Label label) { return base_->Find(label); }
  bool Done() const { return base_->Done(); }
  const Arc& Value() const { return base_->Value(); }
  void Next() { base_->Next(); }
  const F &GetFst() const { return static_cast<const F &>(base_->GetFst()); }

  uint64 Properties(uint64 props) const { return base_->Properties(props); }

  uint32 Flags() const { return base_->Flags(); }

  // Look-ahead methods
  bool LookAheadLabel(Label label) const {
    if (LookAheadCheck()) {
      LBase *lbase = static_cast<LBase *>(base_);
      return lbase->LookAheadLabel(label);
    } else {
      return true;
    }
  }

  bool LookAheadFst(const Fst<Arc> &fst, StateId s) {
    if (LookAheadCheck()) {
      LBase *lbase = static_cast<LBase *>(base_);
      return lbase->LookAheadFst(fst, s);
    } else {
      return true;
    }
  }

  Weight LookAheadWeight() const {
    if (LookAheadCheck()) {
      LBase *lbase = static_cast<LBase *>(base_);
      return lbase->LookAheadWeight();
    } else {
      return Weight::One();
    }
  }

  bool LookAheadPrefix(Arc *arc) const {
    if (LookAheadCheck()) {
      LBase *lbase = static_cast<LBase *>(base_);
      return lbase->LookAheadPrefix(arc);
    } else {
      return false;
    }
  }

  void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false) {
    if (LookAheadCheck()) {
      LBase *lbase = static_cast<LBase *>(base_);
      lbase->InitLookAheadFst(fst, copy);
    }
  }

 private:
  bool LookAheadCheck() const {
    if (!lookahead_) {
      lookahead_ = base_->Flags() &
          (kInputLookAheadMatcher | kOutputLookAheadMatcher);
      if (!lookahead_) {
        FSTERROR() << "LookAheadMatcher: No look-ahead matcher defined";
      }
    }
    return lookahead_;
  }

  MatcherBase<Arc> *base_;
  mutable bool lookahead_;

  void operator=(const LookAheadMatcher<Arc> &);  // disallow
};

}  // namespace fst

#endif  // FST_LIB_LOOKAHEAD_MATCHER_H__
