Search code examples
c++kaldiopenfst

How can I edit the weights of a GrammarFst?


When you have a standard fst you can load it as a MutableFst and do something like:

MutableArcIterator<StdMutableFst> aiter(graph, state_id);
aiter.Seek(position)

auto arc = aiter.Value();
arc.weight = fst::TropicalWeight(NEW_WEIGHT);

aiter.SetValue(arc);

This will change the values of the arcs in memory.

However, when I have ConstFst, which I get from the GrammarFst.instances_ vector with something akin to this:

GrammarFst &fst = const_cast<GrammarFst&>(fst_in);
int32 instance_id = s >> 32;
BaseStateId base_state = static_cast<int32>(s);
const GrammarFst::FstInstance &instance = fst.instances_[instance_id];
const ConstFst<StdArc> *base_fst = instance.fst; // const fst::ConstFst<fst::ArcTpl<fst::TropicalWeightTpl<float> > >* const

I have no way to index into base_fst with a MutableArcIterator as it is a ConstFst. Is this even possible without serious modifications to Kaldi/Openfst?

When I try to do:

MutableArcIterator<StdConstFst > aiter(base_fst, base_state);

I get:

test.cpp:91:72: error: invalid conversion from ‘const fst::ConstFst<fst::ArcTpl<fst::TropicalWeightTpl<float> > >*’ to ‘fst::ConstFst<fst::ArcTpl<fst::TropicalWeightTpl<float> > >*’ [-fpermissive]
             MutableArcIterator<StdConstFst > aiter(base_fst, base_state);

My question:

I need to access the instances_ of a GrammarFst object and change arc weights during runtime. I currently can not do that because GrammarFst.instance_ are ConstFsts.

Solutions that could work:

  • converting the GrammarFst.instances_ to StdFst during run time
  • converting the GrammarFst.instances_ to StdFst when loading from disk
  • saving the GrammarFst.instances_ as StdFst when saving the GrammarFst

Solutions that will not work:

  • saving the entire GrammarFst as a StdFst, (therefore dereferencing the instances_ and copying them into every location in the main fst that they appear. This greatly increases file size (~10X) and will not work for me

Solution

  • Just to close the loop here: GrammarFsts could only be composed of ConstFsts. I ended up making a PR to kaldi to change this so that you can compose them out of VectorFsts, which in turn lets you modify them with a standard MutableArcIterator. https://github.com/kaldi-asr/kaldi/pull/4067