1

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
user2886057
  • 646
  • 1
  • 5
  • 15
  • You can not modify weights of const fst because it is const. You can create StdFst instead of ConstFst and then modify any weight you like. – Nikolay Shmyrev Feb 18 '20 at 22:12
  • Where is your previous question between, I can't seem to find it. – Nikolay Shmyrev Feb 18 '20 at 22:12
  • After modification you can convert StdFst back to ConstFst. – Nikolay Shmyrev Feb 18 '20 at 23:24
  • Okay thanks. Do you know if you can force grammarfst instance fsts to be saved as stdfsts instead of ConstFsts? The problem here is I need to do runtime modification of the weights of a grammarfst. – user2886057 Feb 19 '20 at 17:01
  • Also, can ConstFsts be converted to StdFsts in memory? or do they need to be copied? A link to any documentation or examples would be very helpful. – user2886057 Feb 19 '20 at 17:56
  • You'd better explain what you want to implement to get proper advise. Why do you need to modify grammarfst at all. You can convert grammarfst to stdfst with simple conversion like fstconvert is doing. – Nikolay Shmyrev Feb 19 '20 at 20:03
  • When you use fstconvert to convert a grammarfst to a stdfst, will it deference and copy the `instances_` of the grammarfst? The --write-as-grammar=false option of the make-grammar-fst script does that and it increases the size of my fst file from around 4 GB to 40 GB which I can't load. – user2886057 Feb 20 '20 at 15:37
  • Again, you are doing something wrong. You don't need grammar fst of that size. You'd better describe what you are trying to implement first (the application, not fst details) – Nikolay Shmyrev Feb 20 '20 at 23:06

1 Answers1

1

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

user2886057
  • 646
  • 1
  • 5
  • 15