// vector-fst.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
// Simple concrete, mutable FST whose states and arcs are stored in STL
// vectors.
#ifndef FST_LIB_VECTOR_FST_H__
#define FST_LIB_VECTOR_FST_H__
#include <string>
#include <vector>
using std::vector;
#include <fst/mutable-fst.h>
#include <fst/test-properties.h>
namespace fst {
template <class A> class VectorFst;
template <class F, class G> void Cast(const F &, G *);
// States and arcs implemented by STL vectors, templated on the
// State definition. This does not manage the Fst properties.
template <class State>
class VectorFstBaseImpl : public FstImpl<typename State::Arc> {
public:
typedef typename State::Arc Arc;
typedef typename Arc::Weight Weight;
typedef typename Arc::StateId StateId;
VectorFstBaseImpl() : start_(kNoStateId) {}
~VectorFstBaseImpl() {
for (StateId s = 0; s < states_.size(); ++s)
delete states_[s];
}
StateId Start() const { return start_; }
Weight Final(StateId s) const { return states_[s]->final; }
StateId NumStates() const { return states_.size(); }
size_t NumArcs(StateId s) const { return states_[s]->arcs.size(); }
void SetStart(StateId s) { start_ = s; }
void SetFinal(StateId s, Weight w) { states_[s]->final = w; }
StateId AddState() {
states_.push_back(new State);
return states_.size() - 1;
}
StateId AddState(State *state) {
states_.push_back(state);
return states_.size() - 1;
}
void AddArc(StateId s, const Arc &arc) {
states_[s]->arcs.push_back(arc);
}
void DeleteStates(const vector<StateId>& dstates) {
vector<StateId> newid(states_.size(), 0);
for (size_t i = 0; i < dstates.size(); ++i)
newid[dstates[i]] = kNoStateId;
StateId nstates = 0;
for (StateId s = 0; s < states_.size(); ++s) {
if (newid[s] != kNoStateId) {
newid[s] = nstates;
if (s != nstates)
states_[nstates] = states_[s];
++nstates;
} else {
delete states_[s];
}
}
states_.resize(nstates);
for (StateId s = 0; s < states_.size(); ++s) {
vector<Arc> &arcs = states_[s]->arcs;
size_t narcs = 0;
for (size_t i = 0; i < arcs.size(); ++i) {
StateId t = newid[arcs[i].nextstate];
if (t != kNoStateId) {
arcs[i].nextstate = t;
if (i != narcs)
arcs[narcs] = arcs[i];
++narcs;
} else {
if (arcs[i].ilabel == 0)
--states_[s]->niepsilons;
if (arcs[i].olabel == 0)
--states_[s]->noepsilons;
}
}
arcs.resize(narcs);
}
if (Start() != kNoStateId)
SetStart(newid[Start()]);
}
void DeleteStates() {
for (StateId s = 0; s < states_.size(); ++s)
delete states_[s];
states_.clear();
SetStart(kNoStateId);
}
void DeleteArcs(StateId s, size_t n) {
states_[s]->arcs.resize(states_[s]->arcs.size() - n);
}
void DeleteArcs(StateId s) { states_[s]->arcs.clear(); }
State *GetState(StateId s) { return states_[s]; }
const State *GetState(StateId s) const { return states_[s]; }
void SetState(StateId s, State *state) { states_[s] = state; }
void ReserveStates(StateId n) { states_.reserve(n); }
void ReserveArcs(StateId s, size_t n) { states_[s]->arcs.reserve(n); }
// Provide information needed for generic state iterator
void InitStateIterator(StateIteratorData<Arc> *data) const {
data->base = 0;
data->nstates = states_.size();
}
// Provide information needed for generic arc iterator
void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const {
data->base = 0;
data->narcs = states_[s]->arcs.size();
data->arcs = data->narcs > 0 ? &states_[s]->arcs[0] : 0;
data->ref_count = 0;
}
private:
vector<State *> states_; // States represenation.
StateId start_; // initial state
DISALLOW_COPY_AND_ASSIGN(VectorFstBaseImpl);
};
// Arcs implemented by an STL vector per state.
template <class A>
struct VectorState {
typedef A Arc;
typedef typename A::Weight Weight;
typedef typename A::StateId StateId;
VectorState() : final(Weight::Zero()), niepsilons(0), noepsilons(0) {}
Weight final; // Final weight
vector<A> arcs; // Arcs represenation
size_t niepsilons; // # of input epsilons
size_t noepsilons; // # of output epsilons
};
// This is a VectorFstBaseImpl container that holds VectorState's. It
// manages Fst properties and the # of input and output epsilons.
template <class A>
class VectorFstImpl : public VectorFstBaseImpl< VectorState<A> > {
public:
using FstImpl<A>::SetInputSymbols;
using FstImpl<A>::SetOutputSymbols;
using FstImpl<A>::SetType;
using FstImpl<A>::SetProperties;
using FstImpl<A>::Properties;
using VectorFstBaseImpl<VectorState<A> >::Start;
using VectorFstBaseImpl<VectorState<A> >::NumStates;
using VectorFstBaseImpl<VectorState<A> >::GetState;
using VectorFstBaseImpl<VectorState<A> >::ReserveArcs;
friend class MutableArcIterator< VectorFst<A> >;
typedef VectorFstBaseImpl< VectorState<A> > BaseImpl;
typedef typename A::Weight Weight;
typedef typename A::StateId StateId;
VectorFstImpl() {
SetType("vector");
SetProperties(kNullProperties | kStaticProperties);
}
explicit VectorFstImpl(const Fst<A> &fst);
static VectorFstImpl<A> *Read(istream &strm, const FstReadOptions &opts);
size_t NumInputEpsilons(StateId s) const { return GetState(s)->niepsilons; }
size_t NumOutputEpsilons(StateId s) const { return GetState(s)->noepsilons; }
void SetStart(StateId s) {
BaseImpl::SetStart(s);
SetProperties(SetStartProperties(Properties()));
}
void SetFinal(StateId s, Weight w) {
Weight ow = BaseImpl::Final(s);
BaseImpl::SetFinal(s, w);
SetProperties(SetFinalProperties(Properties(), ow, w));
}
StateId AddState() {
StateId s = BaseImpl::AddState();
SetProperties(AddStateProperties(Properties()));
return s;
}
void AddArc(StateId s, const A &arc) {
VectorState<A> *state = GetState(s);
if (arc.ilabel == 0) {
++state->niepsilons;
}
if (arc.olabel == 0) {
++state->noepsilons;
}
const A *parc = state->arcs.empty() ? 0 : &(state->arcs.back());
SetProperties(AddArcProperties(Properties(), s, arc, parc));
BaseImpl::AddArc(s, arc);
}
void DeleteStates(const vector<StateId> &dstates) {
BaseImpl::DeleteStates(dstates);
SetProperties(DeleteStatesProperties(Properties()));
}
void DeleteStates() {
BaseImpl::DeleteStates();
SetProperties(DeleteAllStatesProperties(Properties(),
kStaticProperties));
}
void DeleteArcs(StateId s, size_t n) {
const vector<A> &arcs = GetState(s)->arcs;
for (size_t i = 0; i < n; ++i) {
size_t j = arcs.size() - i - 1;
if (arcs[j].ilabel == 0)
--GetState(s)->niepsilons;
if (arcs[j].olabel == 0)
--GetState(s)->noepsilons;
}
BaseImpl::DeleteArcs(s, n);
SetProperties(DeleteArcsProperties(Properties()));
}
void DeleteArcs(StateId s) {
GetState(s)->niepsilons = 0;
GetState(s)->noepsilons = 0;
BaseImpl::DeleteArcs(s);
SetProperties(DeleteArcsProperties(Properties()));
}
// Properties always true of this Fst class
static const uint64 kStaticProperties = kExpanded | kMutable;
private:
// Current file format version
static const int kFileVersion = 2;
// Minimum file format version supported
static const int kMinFileVersion = 1;
DISALLOW_COPY_AND_ASSIGN(VectorFstImpl);
};
template <class A> const uint64 VectorFstImpl<A>::kStaticProperties;
template <class A> const int VectorFstImpl<A>::kFileVersion;
template <class A> const int VectorFstImpl<A>::kMinFileVersion;
template <class A>
VectorFstImpl<A>::VectorFstImpl(const Fst<A> &fst) {
SetType("vector");
SetInputSymbols(fst.InputSymbols());
SetOutputSymbols(fst.OutputSymbols());
BaseImpl::SetStart(fst.Start());
if (fst.Properties(kExpanded, false))
BaseImpl::ReserveStates(CountStates(fst));
for (StateIterator< Fst<A> > siter(fst);
!siter.Done();
siter.Next()) {
StateId s = siter.Value();
BaseImpl::AddState();
BaseImpl::SetFinal(s, fst.Final(s));
ReserveArcs(s, fst.NumArcs(s));
for (ArcIterator< Fst<A> > aiter(fst, s);
!aiter.Done();
aiter.Next()) {
const A &arc = aiter.Value();
BaseImpl::AddArc(s, arc);
if (arc.ilabel == 0)
++GetState(s)->niepsilons;
if (arc.olabel == 0)
++GetState(s)->noepsilons;
}
}
SetProperties(fst.Properties(kCopyProperties, false) | kStaticProperties);
}
template <class A>
VectorFstImpl<A> *VectorFstImpl<A>::Read(istream &strm,
const FstReadOptions &opts) {
VectorFstImpl<A> *impl = new VectorFstImpl;
FstHeader hdr;
if (!impl->ReadHeader(strm, opts, kMinFileVersion, &hdr)) {
delete impl;
return 0;
}
impl->BaseImpl::SetStart(hdr.Start());
if (hdr.NumStates() != kNoStateId) {
impl->ReserveStates(hdr.NumStates());
}
StateId s = 0;
for (;hdr.NumStates() == kNoStateId || s < hdr.NumStates(); ++s) {
typename A::Weight final;
if (!final.Read(strm)) break;
impl->BaseImpl::AddState();
VectorState<A> *state = impl->GetState(s);
state->final = final;
int64 narcs;
ReadType(strm, &narcs);
if (!strm) {
LOG(ERROR) << "VectorFst::Read: read failed: " << opts.source;
delete impl;
return 0;
}
impl->ReserveArcs(s, narcs);
for (size_t j = 0; j < narcs; ++j) {
A arc;
ReadType(strm, &arc.ilabel);
ReadType(strm, &arc.olabel);
arc.weight.Read(strm);
ReadType(strm, &arc.nextstate);
if (!strm) {
LOG(ERROR) << "VectorFst::Read: read failed: " << opts.source;
delete impl;
return 0;
}
impl->BaseImpl::AddArc(s, arc);
if (arc.ilabel == 0)
++state->niepsilons;
if (arc.olabel == 0)
++state->noepsilons;
}
}
if (hdr.NumStates() != kNoStateId && s != hdr.NumStates()) {
LOG(ERROR) << "VectorFst::Read: unexpected end of file: " << opts.source;
delete impl;
return 0;
}
return impl;
}
// Converts a string into a weight.
template <class W> class WeightFromString {
public:
W operator()(const string &s);
};
// Generic case fails.
template <class W> inline
W WeightFromString<W>::operator()(const string &s) {
FSTERROR() << "VectorFst::Read: Obsolete file format";
return W::NoWeight();
}
// TropicalWeight version.
template <> inline
TropicalWeight WeightFromString<TropicalWeight>::operator()(const string &s) {
float f;
memcpy(&f, s.data(), sizeof(f));
return TropicalWeight(f);
}
// LogWeight version.
template <> inline
LogWeight WeightFromString<LogWeight>::operator()(const string &s) {
float f;
memcpy(&f, s.data(), sizeof(f));
return LogWeight(f);
}
// Simple concrete, mutable FST. This class attaches interface to
// implementation and handles reference counting, delegating most
// methods to ImplToMutableFst. Supports additional operations:
// ReserveStates and ReserveArcs (cf. STL vectors).
template <class A>
class VectorFst : public ImplToMutableFst< VectorFstImpl<A> > {
public:
friend class StateIterator< VectorFst<A> >;
friend class ArcIterator< VectorFst<A> >;
friend class MutableArcIterator< VectorFst<A> >;
template <class F, class G> friend void Cast(const F &, G *);
typedef A Arc;
typedef typename A::StateId StateId;
typedef VectorFstImpl<A> Impl;
VectorFst() : ImplToMutableFst<Impl>(new Impl) {}
explicit VectorFst(const Fst<A> &fst)
: ImplToMutableFst<Impl>(new Impl(fst)) {}
VectorFst(const VectorFst<A> &fst) : ImplToMutableFst<Impl>(fst) {}
// Get a copy of this VectorFst. See Fst<>::Copy() for further doc.
virtual VectorFst<A> *Copy(bool safe = false) const {
return new VectorFst<A>(*this);
}
VectorFst<A> &operator=(const VectorFst<A> &fst) {
SetImpl(fst.GetImpl(), false);
return *this;
}
virtual VectorFst<A> &operator=(const Fst<A> &fst) {
if (this != &fst) SetImpl(new Impl(fst));
return *this;
}
// Read a VectorFst from an input stream; return NULL on error
static VectorFst<A> *Read(istream &strm, const FstReadOptions &opts) {
Impl* impl = Impl::Read(strm, opts);
return impl ? new VectorFst<A>(impl) : 0;
}
// Read a VectorFst from a file; return NULL on error
// Empty filename reads from standard input
static VectorFst<A> *Read(const string &filename) {
Impl* impl = ImplToExpandedFst<Impl, MutableFst<A> >::Read(filename);
return impl ? new VectorFst<A>(impl) : 0;
}
virtual bool Write(ostream &strm, const FstWriteOptions &opts) const {
return WriteFst(*this, strm, opts);
}
virtual bool Write(const string &filename) const {
return Fst<A>::WriteFile(filename);
}
template <class F>
static bool WriteFst(const F &fst, ostream &strm,
const FstWriteOptions &opts);
void ReserveStates(StateId n) {
MutateCheck();
GetImpl()->ReserveStates(n);
}
void ReserveArcs(StateId s, size_t n) {
MutateCheck();
GetImpl()->ReserveArcs(s, n);
}
virtual void InitStateIterator(StateIteratorData<Arc> *data) const {
GetImpl()->InitStateIterator(data);
}
virtual void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const {
GetImpl()->InitArcIterator(s, data);
}
virtual inline
void InitMutableArcIterator(StateId s, MutableArcIteratorData<A> *);
private:
explicit VectorFst(Impl *impl) : ImplToMutableFst<Impl>(impl) {}
// Makes visible to friends.
Impl *GetImpl() const { return ImplToFst< Impl, MutableFst<A> >::GetImpl(); }
void SetImpl(Impl *impl, bool own_impl = true) {
ImplToFst< Impl, MutableFst<A> >::SetImpl(impl, own_impl);
}
void MutateCheck() { return ImplToMutableFst<Impl>::MutateCheck(); }
};
// Specialization for VectorFst; see generic version in fst.h
// for sample usage (but use the VectorFst type!). This version
// should inline.
template <class A>
class StateIterator< VectorFst<A> > {
public:
typedef typename A::StateId StateId;
explicit StateIterator(const VectorFst<A> &fst)
: nstates_(fst.GetImpl()->NumStates()), s_(0) {}
bool Done() const { return s_ >= nstates_; }
StateId Value() const { return s_; }
void Next() { ++s_; }
void Reset() { s_ = 0; }
private:
StateId nstates_;
StateId s_;
DISALLOW_COPY_AND_ASSIGN(StateIterator);
};
// Writes Fst to file, will call CountStates so may involve two passes if
// called from an Fst that is not derived from Expanded.
template <class A>
template <class F>
bool VectorFst<A>::WriteFst(const F &fst, ostream &strm,
const FstWriteOptions &opts) {
static const int kFileVersion = 2;
bool update_header = true;
FstHeader hdr;
hdr.SetStart(fst.Start());
hdr.SetNumStates(kNoStateId);
size_t start_offset = 0;
if (fst.Properties(kExpanded, false) || (start_offset = strm.tellp()) != -1) {
hdr.SetNumStates(CountStates(fst));
update_header = false;
}
uint64 properties = fst.Properties(kCopyProperties, false) |
VectorFstImpl<A>::kStaticProperties;
FstImpl<A>::WriteFstHeader(fst, strm, opts, kFileVersion, "vector",
properties, &hdr);
StateId num_states = 0;
for (StateIterator<F> siter(fst); !siter.Done(); siter.Next()) {
typename A::StateId s = siter.Value();
fst.Final(s).Write(strm);
int64 narcs = fst.NumArcs(s);
WriteType(strm, narcs);
for (ArcIterator<F> aiter(fst, s); !aiter.Done(); aiter.Next()) {
const A &arc = aiter.Value();
WriteType(strm, arc.ilabel);
WriteType(strm, arc.olabel);
arc.weight.Write(strm);
WriteType(strm, arc.nextstate);
}
num_states++;
}
strm.flush();
if (!strm) {
LOG(ERROR) << "VectorFst::Write: write failed: " << opts.source;
return false;
}
if (update_header) {
hdr.SetNumStates(num_states);
return FstImpl<A>::UpdateFstHeader(fst, strm, opts, kFileVersion, "vector",
properties, &hdr, start_offset);
} else {
if (num_states != hdr.NumStates()) {
LOG(ERROR) << "Inconsistent number of states observed during write";
return false;
}
}
return true;
}
// Specialization for VectorFst; see generic version in fst.h
// for sample usage (but use the VectorFst type!). This version
// should inline.
template <class A>
class ArcIterator< VectorFst<A> > {
public:
typedef typename A::StateId StateId;
ArcIterator(const VectorFst<A> &fst, StateId s)
: arcs_(fst.GetImpl()->GetState(s)->arcs), i_(0) {}
bool Done() const { return i_ >= arcs_.size(); }
const A& Value() const { return arcs_[i_]; }
void Next() { ++i_; }
void Reset() { i_ = 0; }
void Seek(size_t a) { i_ = a; }
size_t Position() const { return i_; }
uint32 Flags() const {
return kArcValueFlags;
}
void SetFlags(uint32 f, uint32 m) {}
private:
const vector<A>& arcs_;
size_t i_;
DISALLOW_COPY_AND_ASSIGN(ArcIterator);
};
// Specialization for VectorFst; see generic version in fst.h
// for sample usage (but use the VectorFst type!). This version
// should inline.
template <class A>
class MutableArcIterator< VectorFst<A> >
: public MutableArcIteratorBase<A> {
public:
typedef typename A::StateId StateId;
typedef typename A::Weight Weight;
MutableArcIterator(VectorFst<A> *fst, StateId s) : i_(0) {
fst->MutateCheck();
state_ = fst->GetImpl()->GetState(s);
properties_ = &fst->GetImpl()->properties_;
}
bool Done() const { return i_ >= state_->arcs.size(); }
const A& Value() const { return state_->arcs[i_]; }
void Next() { ++i_; }
size_t Position() const { return i_; }
void Reset() { i_ = 0; }
void Seek(size_t a) { i_ = a; }
void SetValue(const A &arc) {
A& oarc = state_->arcs[i_];
if (oarc.ilabel != oarc.olabel)
*properties_ &= ~kNotAcceptor;
if (oarc.ilabel == 0) {
--state_->niepsilons;
*properties_ &= ~kIEpsilons;
if (oarc.olabel == 0)
*properties_ &= ~kEpsilons;
}
if (oarc.olabel == 0) {
--state_->noepsilons;
*properties_ &= ~kOEpsilons;
}
if (oarc.weight != Weight::Zero() && oarc.weight != Weight::One())
*properties_ &= ~kWeighted;
oarc = arc;
if (arc.ilabel != arc.olabel) {
*properties_ |= kNotAcceptor;
*properties_ &= ~kAcceptor;
}
if (arc.ilabel == 0) {
++state_->niepsilons;
*properties_ |= kIEpsilons;
*properties_ &= ~kNoIEpsilons;
if (arc.olabel == 0) {
*properties_ |= kEpsilons;
*properties_ &= ~kNoEpsilons;
}
}
if (arc.olabel == 0) {
++state_->noepsilons;
*properties_ |= kOEpsilons;
*properties_ &= ~kNoOEpsilons;
}
if (arc.weight != Weight::Zero() && arc.weight != Weight::One()) {
*properties_ |= kWeighted;
*properties_ &= ~kUnweighted;
}
*properties_ &= kSetArcProperties | kAcceptor | kNotAcceptor |
kEpsilons | kNoEpsilons | kIEpsilons | kNoIEpsilons |
kOEpsilons | kNoOEpsilons | kWeighted | kUnweighted;
}
uint32 Flags() const {
return kArcValueFlags;
}
void SetFlags(uint32 f, uint32 m) {}
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 bool Done_() const { return Done(); }
virtual const A& Value_() const { return Value(); }
virtual void Next_() { Next(); }
virtual size_t Position_() const { return Position(); }
virtual void Reset_() { Reset(); }
virtual void Seek_(size_t a) { Seek(a); }
virtual void SetValue_(const A &a) { SetValue(a); }
uint32 Flags_() const { return Flags(); }
void SetFlags_(uint32 f, uint32 m) { SetFlags(f, m); }
struct VectorState<A> *state_;
uint64 *properties_;
size_t i_;
DISALLOW_COPY_AND_ASSIGN(MutableArcIterator);
};
// Provide information needed for the generic mutable arc iterator
template <class A> inline
void VectorFst<A>::InitMutableArcIterator(
StateId s, MutableArcIteratorData<A> *data) {
data->base = new MutableArcIterator< VectorFst<A> >(this, s);
}
// A useful alias when using StdArc.
typedef VectorFst<StdArc> StdVectorFst;
} // namespace fst
#endif // FST_LIB_VECTOR_FST_H__