PrunedCompactLatticeComposer Class Reference

PrunedCompactLatticeComposer implements an algorithm for pruned composition. More...

Collaboration diagram for PrunedCompactLatticeComposer:

Classes

struct  ComposedStateInfo
 
struct  LatticeStateInfo
 

Public Member Functions

 PrunedCompactLatticeComposer (const ComposeLatticePrunedOptions &opts, const CompactLattice &clat, fst::DeterministicOnDemandFst< fst::StdArc > *det_fst, CompactLattice *composed_clat)
 
void Compose ()
 

Private Types

typedef std::priority_queue< std::pair< BaseFloat, int32 >, std::vector< std::pair< BaseFloat, int32 > >, std::greater< std::pair< BaseFloat, int32 > > > QueueType
 

Private Member Functions

int32 GetCurrentArcLimit () const
 
void ComputeLatticeStateInfo ()
 
void AddFirstState ()
 
void ProcessQueueElement (int32 composed_state_to_expand)
 
void ProcessTransition (int32 composed_src_state, int32 arc_index)
 
void RecomputePruningInfo ()
 
void GetTopsortedStateList (std::vector< int32 > *composed_states) const
 
void ComputeForwardCosts (const std::vector< int32 > &composed_states)
 
void ComputeBackwardCosts (const std::vector< int32 > &composed_states)
 
void ComputeDeltaBackwardCosts (const std::vector< int32 > &composed_states)
 

Private Attributes

bool output_reached_final_
 
float depth_penalty_
 
const ComposeLatticePrunedOptionsopts_
 
const CompactLatticeclat_in_
 
fst::DeterministicOnDemandFst< fst::StdArc > * det_fst_
 
CompactLatticeclat_out_
 
int32 num_arcs_out_
 
std::vector< LatticeStateInfolat_state_info_
 
double lat_best_cost_
 
double output_best_cost_
 
BaseFloat current_cutoff_
 
QueueType composed_state_queue_
 
std::vector< ComposedStateInfocomposed_state_info_
 
unordered_map< std::pair< int32, int32 >, int32, PairHasher< int32 > > pair_to_state_
 
std::set< int32accessed_lat_states_
 

Detailed Description

PrunedCompactLatticeComposer implements an algorithm for pruned composition.

It uses a heuristic (like the heuristics used in A*) to estimate the cost to the end of a graph, of the best path that we might get if we expand a particular transition out of a particular state. This enables us to use a priority queue to expand arcs in the composed result in an order roughly from most promising to least promising.

Because some of the quantities used in the heuristic are hard to efficiently keep updated as the composed output is incrementally added to, we periodically recompute these quantities (c.f. RecomputePruningInfo()). In order to prevent this periodic recomputation from dominating the time taken to produce the lattice, we recompute these things on a schedule where, between each computation, we allow the size of the output to grow by a constant factor (default: 1.5). Since the time taken to do the recomputation of quantities used in the heuristic takes time linear in the size of the so-far existing composed output, doing so on this type of schedule will add no more than a constant factor to the runtime.

Definition at line 47 of file compose-lattice-pruned.cc.

Member Typedef Documentation

◆ QueueType

typedef std::priority_queue<std::pair<BaseFloat, int32>, std::vector<std::pair<BaseFloat, int32> >, std::greater<std::pair<BaseFloat, int32> > > QueueType
private

Definition at line 347 of file compose-lattice-pruned.cc.

Constructor & Destructor Documentation

◆ PrunedCompactLatticeComposer()

Definition at line 621 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::clat_out_, and PrunedCompactLatticeComposer::depth_penalty_.

625  : output_reached_final_(false),
626  opts_(opts), clat_in_(clat_in), det_fst_(det_fst),
627  clat_out_(composed_clat),
628  num_arcs_out_(0),
629  output_best_cost_(std::numeric_limits<double>::infinity()),
630  current_cutoff_(std::numeric_limits<double>::infinity()) {
631  clat_out_->DeleteStates();
632  depth_penalty_ = -1000;
633 }
const ComposeLatticePrunedOptions & opts_
fst::DeterministicOnDemandFst< fst::StdArc > * det_fst_

Member Function Documentation

◆ AddFirstState()

void AddFirstState ( )
private

Definition at line 636 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::accessed_lat_states_, PrunedCompactLatticeComposer::ComposedStateInfo::arc_delta_cost, PrunedCompactLatticeComposer::ComposedStateInfo::backward_cost, PrunedCompactLatticeComposer::clat_out_, PrunedCompactLatticeComposer::composed_state_info_, PrunedCompactLatticeComposer::composed_state_queue_, PrunedCompactLatticeComposer::ComposedStateInfo::delta_backward_cost, PrunedCompactLatticeComposer::ComposedStateInfo::depth, PrunedCompactLatticeComposer::det_fst_, PrunedCompactLatticeComposer::ComposedStateInfo::forward_cost, KALDI_ASSERT, PrunedCompactLatticeComposer::ComposedStateInfo::lat_state, PrunedCompactLatticeComposer::lat_state_info_, PrunedCompactLatticeComposer::ComposedStateInfo::lm_state, PrunedCompactLatticeComposer::pair_to_state_, PrunedCompactLatticeComposer::ComposedStateInfo::prev_composed_state, PrunedCompactLatticeComposer::ComposedStateInfo::sorted_arc_index, and DeterministicOnDemandFst< Arc >::Start().

Referenced by PrunedCompactLatticeComposer::Compose().

636  {
637  int32 state_id = clat_out_->AddState();
638  clat_out_->SetStart(state_id);
639  KALDI_ASSERT(state_id == 0);
640  composed_state_info_.resize(1);
641  ComposedStateInfo &composed_state = composed_state_info_[0];
642  composed_state.lat_state = 0;
643  composed_state.lm_state = det_fst_->Start();
644  composed_state.depth = 0;
645  composed_state.forward_cost = 0.0;
646  composed_state.backward_cost = std::numeric_limits<double>::infinity();
647  composed_state.delta_backward_cost = 0.0;
648  composed_state.prev_composed_state = -1;
649  composed_state.sorted_arc_index = 0;
650  composed_state.arc_delta_cost = 0.0; // the first arc_delta_cost is always 0.0
651  // due to sorting; no need to look it up.
652  lat_state_info_[0].composed_states.push_back(state_id);
653  accessed_lat_states_.insert(state_id);
654  pair_to_state_[std::pair<int32, int32>(0, det_fst_->Start())] = state_id;
655 
656  BaseFloat expected_cost_offset = 0.0; // the formula simplifies to zero
657  // in this case.
659  std::pair<BaseFloat, int32>(expected_cost_offset,
660  state_id)); // actually (0.0, 0).
661 
662 }
std::vector< LatticeStateInfo > lat_state_info_
std::vector< ComposedStateInfo > composed_state_info_
fst::DeterministicOnDemandFst< fst::StdArc > * det_fst_
kaldi::int32 int32
virtual StateId Start()=0
unordered_map< std::pair< int32, int32 >, int32, PairHasher< int32 > > pair_to_state_
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ Compose()

void Compose ( )

Definition at line 887 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::AddFirstState(), PrunedCompactLatticeComposer::clat_in_, PrunedCompactLatticeComposer::clat_out_, PrunedCompactLatticeComposer::composed_state_info_, PrunedCompactLatticeComposer::composed_state_queue_, PrunedCompactLatticeComposer::ComputeLatticeStateInfo(), PrunedCompactLatticeComposer::GetCurrentArcLimit(), kaldi::GetVerboseLevel(), KALDI_VLOG, KALDI_WARN, PrunedCompactLatticeComposer::lat_best_cost_, ComposeLatticePrunedOptions::max_arcs, PrunedCompactLatticeComposer::num_arcs_out_, PrunedCompactLatticeComposer::opts_, PrunedCompactLatticeComposer::output_best_cost_, PrunedCompactLatticeComposer::ProcessQueueElement(), PrunedCompactLatticeComposer::RecomputePruningInfo(), kaldi::TopSortCompactLatticeIfNeeded(), and kaldi::TotalNumArcs().

Referenced by kaldi::ComposeCompactLatticePruned().

887  {
888  if (clat_in_.NumStates() == 0) {
889  KALDI_WARN << "Input lattice to composition is empty.";
890  return;
891  }
893  AddFirstState();
894  // while (we have not reached final state ||
895  // num-arcs produced < target num-arcs) { ...
896  while (output_best_cost_ == std::numeric_limits<double>::infinity() ||
899  int32 this_iter_arc_limit = GetCurrentArcLimit();
900  while (num_arcs_out_ < this_iter_arc_limit &&
901  !composed_state_queue_.empty()) {
902  int32 src_composed_state = composed_state_queue_.top().second;
903  composed_state_queue_.pop();
904  ProcessQueueElement(src_composed_state);
905  }
906  if (composed_state_queue_.empty())
907  break;
908  }
909 
910  fst::Connect(clat_out_);
912 
913  if (GetVerboseLevel() >= 2) {
914  int32 num_arcs_in = TotalNumArcs(clat_in_),
915  orig_num_arcs_out = num_arcs_out_,
916  num_arcs_out = TotalNumArcs(*clat_out_),
917  num_states_in = clat_in_.NumStates(),
918  orig_num_states_out = composed_state_info_.size(),
919  num_states_out = clat_out_->NumStates();
920  std::ostringstream os;
921  os << "Input lattice had " << num_arcs_in << '/' << num_states_in
922  << " arcs/states; output lattice has " << num_arcs_out << '/'
923  << num_states_out;
924  if (num_arcs_out != orig_num_arcs_out) {
925  os << " (before pruning: " << orig_num_arcs_out << '/'
926  << orig_num_states_out << ")";
927  }
928  if (!composed_state_queue_.empty()) {
929  // Below, composed_state_queue_.top().first + lat_best_cost is an
930  // expected-cost of the best path from the composed output that we *did
931  // not* expand. This, minus the best cost in the output compact lattice,
932  // can be interpreted as the beam that we effecctively pruned the output
933  // lattice to.
934  BaseFloat effective_beam =
936  os << ". Effective beam was " << effective_beam;
937  }
938  KALDI_VLOG(2) << os.str();
939  }
940 
941  if (clat_out_->NumStates() == 0) {
942  KALDI_WARN << "Composed lattice has no states: something went wrong.";
943  }
944 }
std::vector< ComposedStateInfo > composed_state_info_
const ComposeLatticePrunedOptions & opts_
int32 GetVerboseLevel()
Get verbosity level, usually set via command line &#39;–verbose=&#39; switch.
Definition: kaldi-error.h:60
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
void ProcessQueueElement(int32 composed_state_to_expand)
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
void TopSortCompactLatticeIfNeeded(CompactLattice *clat)
Topologically sort the compact lattice if not already topologically sorted.
static int32 TotalNumArcs(const CompactLattice &clat)

◆ ComputeBackwardCosts()

void ComputeBackwardCosts ( const std::vector< int32 > &  composed_states)
private

Definition at line 475 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::LatticeStateInfo::backward_cost, PrunedCompactLatticeComposer::ComposedStateInfo::backward_cost, PrunedCompactLatticeComposer::clat_out_, PrunedCompactLatticeComposer::composed_state_info_, fst::ConvertToCost(), PrunedCompactLatticeComposer::current_cutoff_, PrunedCompactLatticeComposer::lat_best_cost_, ComposeLatticePrunedOptions::lattice_compose_beam, PrunedCompactLatticeComposer::opts_, and PrunedCompactLatticeComposer::output_best_cost_.

Referenced by PrunedCompactLatticeComposer::RecomputePruningInfo().

476  {
477  // Access the composed states in reverse topological order from latest to
478  // earliest.
479  std::vector<int32>::const_reverse_iterator iter = composed_states.rbegin(),
480  end = composed_states.rend();
481  for (; iter != end; ++iter) {
482  int32 composed_state_index = *iter;
483  ComposedStateInfo &info = composed_state_info_[composed_state_index];
484  double backward_cost =
485  ConvertToCost(clat_out_->Final(composed_state_index));
486  fst::ArcIterator<CompactLattice> aiter(*clat_out_,
487  composed_state_index);
488  for (; !aiter.Done(); aiter.Next()) {
489  const CompactLatticeArc &arc = aiter.Value();
490  double arc_cost = ConvertToCost(arc.weight),
491  next_backward_cost = composed_state_info_[arc.nextstate].backward_cost,
492  this_backward_cost = arc_cost + next_backward_cost;
493  if (this_backward_cost < backward_cost)
494  backward_cost = this_backward_cost;
495  }
496  // It's OK if at this point, backward_cost is still +infinity. This means
497  // that this state cannot reach the end yet, which means we have not yet
498  // expanded any path from this state all the way to a final-state of the
499  // output.
500  info.backward_cost = backward_cost;
501  }
502  output_best_cost_ = composed_state_info_[0].backward_cost;
503  // See the declaration of current_cutoff_ for more information. Note: on
504  // early iterations, before any path reaches a final state of the composed
505  // lattice, current_cutoff_ may be +infinity, and this is OK.
508 }
std::vector< ComposedStateInfo > composed_state_info_
const ComposeLatticePrunedOptions & opts_
kaldi::int32 int32
double ConvertToCost(const LatticeWeightTpl< Float > &w)
fst::ArcTpl< CompactLatticeWeight > CompactLatticeArc
Definition: kaldi-lattice.h:42

◆ ComputeDeltaBackwardCosts()

void ComputeDeltaBackwardCosts ( const std::vector< int32 > &  composed_states)
private

Definition at line 510 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::ComposedStateInfo::arc_delta_cost, PrunedCompactLatticeComposer::ComposedStateInfo::backward_cost, PrunedCompactLatticeComposer::clat_out_, PrunedCompactLatticeComposer::composed_state_info_, PrunedCompactLatticeComposer::composed_state_queue_, PrunedCompactLatticeComposer::current_cutoff_, PrunedCompactLatticeComposer::ComposedStateInfo::delta_backward_cost, PrunedCompactLatticeComposer::ComposedStateInfo::depth, PrunedCompactLatticeComposer::depth_penalty_, PrunedCompactLatticeComposer::ComposedStateInfo::forward_cost, KALDI_ASSERT, PrunedCompactLatticeComposer::lat_best_cost_, PrunedCompactLatticeComposer::ComposedStateInfo::lat_state, PrunedCompactLatticeComposer::lat_state_info_, and PrunedCompactLatticeComposer::ComposedStateInfo::prev_composed_state.

Referenced by PrunedCompactLatticeComposer::RecomputePruningInfo().

511  {
512 
513  int32 num_states = clat_out_->NumStates();
514  for (int32 composed_state_index = 0; composed_state_index < num_states;
515  ++composed_state_index) {
516  ComposedStateInfo &info = composed_state_info_[composed_state_index];
517  int32 lat_state = info.lat_state;
518  // Note: delta_backward_cost will be +infinity at this stage if the
519  // backward_cost was +infinity. This is OK; we'll set them all to
520  // finite values later in this function.
521  info.delta_backward_cost =
522  info.backward_cost - lat_state_info_[lat_state].backward_cost + info.depth * depth_penalty_;
523  }
524 
525  // 'queue_elements' is a list of items (expected_cost_offset,
526  // composed_state_index) that we are going to add to composed_state_queue_,
527  // after clearing it. It's more efficient to accumulate them as a vector
528  // and add them all at once, than adding them one by one (search online for
529  // "heapify" if this seems confusing).
530  std::vector<std::pair<BaseFloat, int32> > queue_elements;
531  queue_elements.reserve(num_states);
532 
533  double lat_best_cost = lat_best_cost_;
534  BaseFloat current_cutoff = current_cutoff_;
535  std::vector<int32>::const_iterator iter = composed_states.begin(),
536  end = composed_states.end();
537  for (; iter != end; ++iter) {
538  int32 composed_state_index = *iter;
539  ComposedStateInfo &info = composed_state_info_[composed_state_index];
540  if (info.delta_backward_cost - info.delta_backward_cost != 0) {
541  // if info.delta_backward_cost is +infinity...
542  int32 prev_composed_state = info.prev_composed_state;
543  if (prev_composed_state < 0) {
544  KALDI_ASSERT(composed_state_index == 0);
545  info.delta_backward_cost = 0.0;
546  } else {
547  const ComposedStateInfo &prev_info =
548  composed_state_info_[prev_composed_state];
549  // Check that prev_info.delta_backward_cost is finite.
550  KALDI_ASSERT(prev_info.delta_backward_cost -
551  prev_info.delta_backward_cost == 0.0);
552  info.delta_backward_cost = prev_info.delta_backward_cost + depth_penalty_;
553  }
554  }
555  double lat_backward_cost = lat_state_info_[info.lat_state].backward_cost;
556  // See the formula by where expected_cost_offset is declared in the
557  // struct for explanation.
558  BaseFloat expected_cost_offset =
559  info.forward_cost + lat_backward_cost + info.delta_backward_cost +
560  info.arc_delta_cost - lat_best_cost;
561  // If info.expected_cost_offset were real, we'd set it here:
562  //info.expected_cost_offset = expected_cost_offset;
563 
564  // At this point expected_cost_offset may be infinite, if arc_delta_cost was
565  // infinite (reflecting that we processed all the arcs, and the final-state
566  // if applicable, of the lattice state corresponding to this composed state.
567  if (expected_cost_offset < current_cutoff) {
568  queue_elements.push_back(std::pair<BaseFloat, int32>(
569  expected_cost_offset, composed_state_index));
570  }
571  }
572 
573  // Reinitialize composed_state_queue_ from 'queue_elements'.
574  QueueType temp_queue(queue_elements.begin(), queue_elements.end());
575  composed_state_queue_.swap(temp_queue);
576 }
std::vector< LatticeStateInfo > lat_state_info_
std::vector< ComposedStateInfo > composed_state_info_
kaldi::int32 int32
std::priority_queue< std::pair< BaseFloat, int32 >, std::vector< std::pair< BaseFloat, int32 > >, std::greater< std::pair< BaseFloat, int32 > > > QueueType
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeForwardCosts()

void ComputeForwardCosts ( const std::vector< int32 > &  composed_states)
private

Definition at line 428 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::clat_out_, PrunedCompactLatticeComposer::composed_state_info_, fst::ConvertToCost(), PrunedCompactLatticeComposer::ComposedStateInfo::depth, PrunedCompactLatticeComposer::ComposedStateInfo::forward_cost, KALDI_ASSERT, and PrunedCompactLatticeComposer::ComposedStateInfo::prev_composed_state.

Referenced by PrunedCompactLatticeComposer::RecomputePruningInfo().

429  {
430  KALDI_ASSERT(composed_states[0] == 0);
431 
432  // Note: when we initialized composed_state_info_[0]
433  // we set forward_cost = 0.0, prev_composed_state = -1.
434 
435  std::vector<ComposedStateInfo>::iterator
436  state_iter = composed_state_info_.begin(),
437  state_end = composed_state_info_.end();
438 
439  state_iter->depth = 0; // start state has depth 0
440  ++state_iter; // Skip over the start state.
441  // Set all other forward_cost fields to infinity and prev_composed_state to
442  // -1.
443  for (; state_iter != state_end; ++state_iter) {
444  state_iter->forward_cost = std::numeric_limits<double>::infinity();
445  state_iter->prev_composed_state = -1;
446  }
447 
448  std::vector<int32>::const_iterator state_index_iter = composed_states.begin(),
449  state_index_end = composed_states.end();
450  for (; state_index_iter != state_index_end; ++state_index_iter) {
451  int32 composed_state_index = *state_index_iter;
452  const ComposedStateInfo &info = composed_state_info_[
453  composed_state_index];
454  double forward_cost = info.forward_cost;
455  // The next line is a check for infinity. If infinities have appeared, it
456  // either means there is a bug in the algorithm or there were infinities or
457  // NaN's in the lattice.
458  KALDI_ASSERT(forward_cost - forward_cost == 0.0);
459  fst::ArcIterator<CompactLattice> aiter(*clat_out_,
460  composed_state_index);
461  for (; !aiter.Done(); aiter.Next()) {
462  const CompactLatticeArc &arc = aiter.Value();
463  double arc_cost = ConvertToCost(arc.weight),
464  next_forward_cost = forward_cost + arc_cost;
465  ComposedStateInfo &next_info = composed_state_info_[arc.nextstate];
466  if (next_info.forward_cost > next_forward_cost) {
467  next_info.forward_cost = next_forward_cost;
468  next_info.prev_composed_state = composed_state_index;
469  next_info.depth = composed_state_info_[composed_state_index].depth + 1;
470  }
471  }
472  }
473 }
std::vector< ComposedStateInfo > composed_state_info_
kaldi::int32 int32
double ConvertToCost(const LatticeWeightTpl< Float > &w)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
fst::ArcTpl< CompactLatticeWeight > CompactLatticeArc
Definition: kaldi-lattice.h:42

◆ ComputeLatticeStateInfo()

void ComputeLatticeStateInfo ( )
private

Definition at line 578 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::LatticeStateInfo::arc_delta_costs, PrunedCompactLatticeComposer::LatticeStateInfo::backward_cost, PrunedCompactLatticeComposer::clat_in_, fst::ConvertToCost(), KALDI_ASSERT, PrunedCompactLatticeComposer::lat_best_cost_, and PrunedCompactLatticeComposer::lat_state_info_.

Referenced by PrunedCompactLatticeComposer::Compose().

578  {
579  KALDI_ASSERT(clat_in_.Properties(fst::kTopSorted, true) ==
580  fst::kTopSorted && clat_in_.NumStates() > 0 &&
581  clat_in_.Start() == 0);
582  int32 num_lat_states = clat_in_.NumStates();
583  lat_state_info_.resize(num_lat_states);
584 
585  for (int32 s = num_lat_states - 1; s >= 0; s--) {
586  LatticeStateInfo &info = lat_state_info_[s];
587  std::vector<std::pair<double, int32> > arc_costs;
588  double backward_cost = ConvertToCost(clat_in_.Final(s));
589  if (backward_cost != std::numeric_limits<double>::infinity())
590  arc_costs.push_back(std::pair<BaseFloat,int32>(backward_cost, -1));
591  fst::ArcIterator<CompactLattice> aiter(clat_in_, s);
592  int32 arc_index = 0;
593  for (; !aiter.Done(); aiter.Next(), ++arc_index) {
594  const CompactLatticeArc &arc = aiter.Value();
595  KALDI_ASSERT(arc.nextstate > s);
596  backward_cost = lat_state_info_[arc.nextstate].backward_cost +
597  ConvertToCost(arc.weight);
598  KALDI_ASSERT(backward_cost - backward_cost == 0.0 &&
599  "Possibly not all states of input lattice are co-accessible?");
600  arc_costs.push_back(std::pair<BaseFloat,int32>(backward_cost, arc_index));
601  }
602  std::sort(arc_costs.begin(), arc_costs.end());
603  KALDI_ASSERT(!arc_costs.empty() &&
604  "Possibly not all states of input lattice are co-accessible?");
605  backward_cost = arc_costs[0].first;
606  info.backward_cost = backward_cost; // this is the state's backward_cost,
607  // reflecting the best path to the end.
608  info.arc_delta_costs.resize(arc_costs.size());
609  std::vector<std::pair<double, int32> >::const_iterator
610  src_iter = arc_costs.begin(), src_end = arc_costs.end();
611  std::vector<std::pair<BaseFloat, int32> >::iterator
612  dest_iter = info.arc_delta_costs.begin();
613  for (; src_iter != src_end; ++src_iter, ++dest_iter) {
614  dest_iter->first = BaseFloat(src_iter->first - backward_cost);
615  dest_iter->second = src_iter->second;
616  }
617  }
618  lat_best_cost_ = lat_state_info_[0].backward_cost;
619 }
std::vector< LatticeStateInfo > lat_state_info_
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
double ConvertToCost(const LatticeWeightTpl< Float > &w)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
fst::ArcTpl< CompactLatticeWeight > CompactLatticeArc
Definition: kaldi-lattice.h:42

◆ GetCurrentArcLimit()

int32 GetCurrentArcLimit ( ) const
private

Definition at line 399 of file compose-lattice-pruned.cc.

References ComposeLatticePrunedOptions::growth_ratio, ComposeLatticePrunedOptions::initial_num_arcs, KALDI_ASSERT, ComposeLatticePrunedOptions::max_arcs, PrunedCompactLatticeComposer::num_arcs_out_, PrunedCompactLatticeComposer::opts_, and PrunedCompactLatticeComposer::output_best_cost_.

Referenced by PrunedCompactLatticeComposer::Compose().

399  {
400  int32 current_num_arcs = num_arcs_out_;
401  if (current_num_arcs == 0) {
402  return opts_.initial_num_arcs;
403  } else {
405  int32 ans = static_cast<int32>(current_num_arcs *
407  if (ans == current_num_arcs) // make sure the target increases.
408  ans = current_num_arcs + 1;
409  // if we have already reached a final state, then
410  // apply the max_arcs limit.
411  if (output_best_cost_ - output_best_cost_ == 0.0 &&
412  ans > opts_.max_arcs)
413  ans = opts_.max_arcs;
414  return ans;
415  }
416 
417 }
const ComposeLatticePrunedOptions & opts_
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ GetTopsortedStateList()

void GetTopsortedStateList ( std::vector< int32 > *  composed_states) const
private

Definition at line 381 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::accessed_lat_states_, PrunedCompactLatticeComposer::clat_out_, PrunedCompactLatticeComposer::LatticeStateInfo::composed_states, KALDI_ASSERT, and PrunedCompactLatticeComposer::lat_state_info_.

Referenced by PrunedCompactLatticeComposer::RecomputePruningInfo().

382  {
383  composed_states->clear();
384  composed_states->reserve(clat_out_->NumStates());
385  std::set<int32>::const_iterator iter = accessed_lat_states_.begin(),
386  end = accessed_lat_states_.end();
387  for (; iter != end; ++iter) {
388  int32 lat_state = *iter;
389  const LatticeStateInfo &input_lat_info = lat_state_info_[lat_state];
390  composed_states->insert(composed_states->end(),
391  input_lat_info.composed_states.begin(),
392  input_lat_info.composed_states.end());
393  }
394  KALDI_ASSERT((*composed_states)[0] == 0 &&
395  static_cast<int32>(composed_states->size()) ==
396  clat_out_->NumStates());
397 }
std::vector< LatticeStateInfo > lat_state_info_
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ProcessQueueElement()

void ProcessQueueElement ( int32  composed_state_to_expand)
private

Definition at line 665 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::LatticeStateInfo::arc_delta_costs, PrunedCompactLatticeComposer::LatticeStateInfo::backward_cost, PrunedCompactLatticeComposer::clat_in_, PrunedCompactLatticeComposer::clat_out_, PrunedCompactLatticeComposer::composed_state_info_, PrunedCompactLatticeComposer::composed_state_queue_, fst::ConvertToCost(), PrunedCompactLatticeComposer::current_cutoff_, PrunedCompactLatticeComposer::depth_penalty_, PrunedCompactLatticeComposer::det_fst_, DeterministicOnDemandFst< Arc >::Final(), KALDI_ASSERT, PrunedCompactLatticeComposer::lat_best_cost_, PrunedCompactLatticeComposer::lat_state_info_, PrunedCompactLatticeComposer::output_reached_final_, PrunedCompactLatticeComposer::ProcessTransition(), and PrunedCompactLatticeComposer::RecomputePruningInfo().

Referenced by PrunedCompactLatticeComposer::Compose().

666  {
667  KALDI_ASSERT(static_cast<size_t>(src_composed_state) <
668  composed_state_info_.size());
669 
670  ComposedStateInfo &src_composed_state_info = composed_state_info_[
671  src_composed_state];
672  int32 lat_state = src_composed_state_info.lat_state;
673  const LatticeStateInfo &lat_state_info =
674  lat_state_info_[lat_state];
675 
676  int32 sorted_arc_index = src_composed_state_info.sorted_arc_index,
677  num_sorted_arcs = lat_state_info.arc_delta_costs.size();
678  // note: num_sorted_arcs will be the number of arcs from this
679  // lattice state; plus one if there is a final-prob.
680  KALDI_ASSERT(sorted_arc_index >= 0);
681 
682  { // this block update the state's 'sorted_arc_index', 'arc_delta_cost' and
683  // 'expected_cost_offset' to reflect the fact that (by the time we exit from
684  // this function) we will have processed this arc (or the final-prob);
685  // it also re-inserts this state into the queue, if appropriate.
686  BaseFloat expected_cost_offset;
687  if (sorted_arc_index + 1 == num_sorted_arcs) {
688  src_composed_state_info.sorted_arc_index = -1;
689  src_composed_state_info.arc_delta_cost =
690  std::numeric_limits<BaseFloat>::infinity();
691  expected_cost_offset =
692  std::numeric_limits<BaseFloat>::infinity();
693  } else {
694  src_composed_state_info.sorted_arc_index = sorted_arc_index + 1;
695  src_composed_state_info.arc_delta_cost =
696  lat_state_info.arc_delta_costs[sorted_arc_index+1].first;
697  expected_cost_offset =
698  (src_composed_state_info.forward_cost +
699  lat_state_info.backward_cost +
700  src_composed_state_info.delta_backward_cost +
701  src_composed_state_info.arc_delta_cost - lat_best_cost_);
702  }
703  // We do '<' here rather than '<=', so that if current_cutoff_ is infinity
704  // and expected_cost_offset is infinity (because we've exhausted all the
705  // transitions from this state, and sorted_arc_index is now -1), we don't
706  // add this element to the queue.
707  if (expected_cost_offset < current_cutoff_) {
708  // this state has another exit arc (or final prob) that is good
709  // enough to re-enter into the queue. Note: if we are processing
710  // an arc out of this state and the destination state is new,
711  // we may also add something new to the queue at that time.
712 
713  // the following call should be equivalent to
714  // composed_state_queue_.push(std::pair<BaseFloat,int32>(...)) with
715  // the same pair of args.
716  composed_state_queue_.emplace(
717  expected_cost_offset, src_composed_state);
718  }
719  }
720 
721  int32 arc_index = lat_state_info.arc_delta_costs[sorted_arc_index].second;
722  if (arc_index < 0) { // This (arc_index == -1) means it is not really an arc
723  // index; it's a final-prob.
724  int32 lm_state = src_composed_state_info.lm_state;
725  BaseFloat lm_final_cost = det_fst_->Final(lm_state).Value();
726  if (lm_final_cost != std::numeric_limits<BaseFloat>::infinity()) {
727  // If there is a final-prob on this LM state (note: there always will be
728  // for conventional language models), then add the final-prob of this
729  // state...
730  CompactLattice::Weight final_weight = clat_in_.Final(lat_state);
731  // assume 'final_weight' is not Zero(); otherwise the final-prob should
732  // not have been present in 'arc_delta_costs'.
733  Lattice::Weight final_lat_weight = final_weight.Weight();
734  final_lat_weight.SetValue1(final_lat_weight.Value1() +
735  lm_final_cost);
736  final_weight.SetWeight(final_lat_weight);
737  clat_out_->SetFinal(src_composed_state, final_weight);
738  double final_cost = ConvertToCost(final_lat_weight);
739  if (final_cost < src_composed_state_info.backward_cost)
740  src_composed_state_info.backward_cost = final_cost;
741  if (!output_reached_final_) {
742  output_reached_final_ = true;
743  depth_penalty_ = 0.0;
745  }
746  }
747  } else {
748  // It really was an arc. This code is very complicated, so we make it its
749  // own function.
750  ProcessTransition(src_composed_state, arc_index);
751  }
752 }
std::vector< LatticeStateInfo > lat_state_info_
std::vector< ComposedStateInfo > composed_state_info_
virtual Weight Final(StateId s)=0
fst::DeterministicOnDemandFst< fst::StdArc > * det_fst_
void ProcessTransition(int32 composed_src_state, int32 arc_index)
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
double ConvertToCost(const LatticeWeightTpl< Float > &w)
fst::StdArc::Weight Weight
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ProcessTransition()

void ProcessTransition ( int32  composed_src_state,
int32  arc_index 
)
private

Definition at line 754 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::accessed_lat_states_, PrunedCompactLatticeComposer::ComposedStateInfo::arc_delta_cost, PrunedCompactLatticeComposer::LatticeStateInfo::backward_cost, PrunedCompactLatticeComposer::ComposedStateInfo::backward_cost, PrunedCompactLatticeComposer::clat_in_, PrunedCompactLatticeComposer::clat_out_, PrunedCompactLatticeComposer::composed_state_info_, PrunedCompactLatticeComposer::composed_state_queue_, PrunedCompactLatticeComposer::LatticeStateInfo::composed_states, fst::ConvertToCost(), PrunedCompactLatticeComposer::current_cutoff_, PrunedCompactLatticeComposer::ComposedStateInfo::delta_backward_cost, PrunedCompactLatticeComposer::ComposedStateInfo::depth, PrunedCompactLatticeComposer::depth_penalty_, PrunedCompactLatticeComposer::det_fst_, PrunedCompactLatticeComposer::ComposedStateInfo::forward_cost, DeterministicOnDemandFst< Arc >::GetArc(), KALDI_ASSERT, PrunedCompactLatticeComposer::lat_best_cost_, PrunedCompactLatticeComposer::ComposedStateInfo::lat_state, PrunedCompactLatticeComposer::lat_state_info_, PrunedCompactLatticeComposer::ComposedStateInfo::lm_state, PrunedCompactLatticeComposer::num_arcs_out_, PrunedCompactLatticeComposer::pair_to_state_, PrunedCompactLatticeComposer::ComposedStateInfo::prev_composed_state, PrunedCompactLatticeComposer::ComposedStateInfo::sorted_arc_index, and fst::Times().

Referenced by PrunedCompactLatticeComposer::ProcessQueueElement().

755  {
756  // Make src_composed_state a const pointer not a reference, as we may have to
757  // modify the pointer if composed_state_info_ is resized.
758  const ComposedStateInfo *src_info = &(composed_state_info_[
759  src_composed_state]);
760  int32 src_lat_state = src_info->lat_state;
761  // Get the arc we are going to expand.
762  fst::ArcIterator<CompactLattice> aiter(clat_in_, src_lat_state);
763  aiter.Seek(arc_index);
764  const CompactLatticeArc &lat_arc = aiter.Value();
765  // Note: this code is for CompactLatticeArc, in which the ilabel and olabel
766  // are the same, but we're writing it in such a way that it will naturally
767  // generalize to LatticeArc, so there are separate variables for the ilabel
768  // and the olabel.
769  int32 dest_lat_state = lat_arc.nextstate,
770  ilabel = lat_arc.ilabel,
771  olabel = lat_arc.olabel;
772  // Note: we expect that ilabel == olabel, since this is a CompactLattice, but this
773  // may not be so if we extend this to work with Lattice.
774  fst::StdArc lm_arc;
775 
776  // the input lattice might have epsilons
777  if (olabel == 0) {
778  lm_arc.ilabel = 0;
779  lm_arc.olabel = 0;
780  lm_arc.nextstate = src_info->lm_state;
781  lm_arc.weight = fst::StdArc::Weight(0.0);
782  } else if (!det_fst_->GetArc(src_info->lm_state, olabel, &lm_arc)) {
783  // for normal language models we don't expect this to happen, but the
784  // appropriate behavior is to do nothing; the composed arc does not exist,
785  // so there is no arc to add and no new state to create.
786  return;
787  }
788  int32 dest_lm_state = lm_arc.nextstate;
789  // The following assertion is necessary because CompactLattice cannot support
790  // different ilabel vs. olabel; and also it's an expectation about
791  // language-models.
792  KALDI_ASSERT(lm_arc.ilabel == lm_arc.olabel);
793 
794  LatticeStateInfo &dest_lat_state_info =
795  lat_state_info_[dest_lat_state];
796 
797  int32 dest_composed_state;
798  ComposedStateInfo *dest_info;
799 
800  { // The next block works out 'dest_composed_state' and
801  // 'dest_info', and if the destination state did not already
802  // exist, creates a new composed state.
803  typedef std::unordered_map<std::pair<int32,int32>, int32,
804  PairHasher<int32> > MapType;
805  int32 new_composed_state = clat_out_->NumStates();
806  std::pair<const std::pair<int32,int32>, int32> value(
807  std::pair<int32,int32>(dest_lat_state, dest_lm_state), new_composed_state);
808  std::pair<MapType::iterator, bool> ret =
809  pair_to_state_.insert(value);
810  if (ret.second) {
811  // Successfully inserted: this dest-state did not already exist. Most of
812  // the rest of this block deals with the consequences of adding a new
813  // state.
814  int32 ans = clat_out_->AddState();
815  KALDI_ASSERT(ans == new_composed_state);
816  dest_composed_state = new_composed_state;
817  composed_state_info_.resize(dest_composed_state + 1);
818  dest_info = &(composed_state_info_[dest_composed_state]);
819  // Re-assign src_composed_state as the vector might have been reallocated.
820  src_info = &(composed_state_info_[src_composed_state]);
821  if (dest_lat_state_info.composed_states.empty())
822  accessed_lat_states_.insert(dest_lat_state);
823  dest_lat_state_info.composed_states.push_back(new_composed_state);
824  dest_info->lat_state = dest_lat_state;
825  dest_info->lm_state = dest_lm_state;
826  dest_info->depth = src_info->depth + 1;
827  dest_info->forward_cost =
828  src_info->forward_cost +
829  ConvertToCost(lat_arc.weight) + lm_arc.weight.Value();
830  dest_info->backward_cost =
831  std::numeric_limits<double>::infinity();
832  dest_info->delta_backward_cost =
833  src_info->delta_backward_cost + dest_info->depth * depth_penalty_;
834  // The 'prev_composed_state' field will not be read again until after it's
835  // overwritten; we set it as below only for debugging purposes (the
836  // negation is also for debugging purposes).
837  dest_info->prev_composed_state = -src_composed_state;
838  dest_info->sorted_arc_index = 0;
839  dest_info->arc_delta_cost = 0.0;
840  // Note: in the expression below, which can be understood with reference
841  // to the comment by the declaration of the phantom variable
842  // 'expected_cost_offset', 'arc_delta_cost' is known to equal 0.0 so it
843  // has been removed.
844  BaseFloat expected_cost_offset =
845  (dest_info->forward_cost +
846  dest_lat_state_info.backward_cost +
847  dest_info->delta_backward_cost -
849  if (expected_cost_offset < current_cutoff_) {
850  // the following call should be equivalent to
851  // composed_state_queue_.push(std::pair<BaseFloat,int32>(...)) with
852  // the same pair of args.
853  composed_state_queue_.emplace(expected_cost_offset,
854  dest_composed_state);
855  }
856  } else { // the destination composed state already existed.
857  dest_composed_state = ret.first->second;
858  dest_info = &(composed_state_info_[dest_composed_state]);
859  }
860  }
861  // Add the arc from the src to dest state in the composed output.
862  CompactLatticeArc new_arc;
863  new_arc.nextstate = dest_composed_state;
864  // Actually the ilabel and olabel are the same, but writing it this way will
865  // generalize better to type Lattice if we need that later.
866  new_arc.ilabel = ilabel;
867  new_arc.olabel = olabel;
868  new_arc.weight = lat_arc.weight;
869  // 'weight' is the weight part, as opposed to the string part.
870  LatticeArc::Weight weight = new_arc.weight.Weight();
871  // include the LM-arc's weight in the weight of the new arc.
872  weight.SetValue1(fst::Times(weight.Value1(), lm_arc.weight).Value());
873  new_arc.weight.SetWeight(weight);
874  clat_out_->AddArc(src_composed_state, new_arc);
875  num_arcs_out_++;
876 }
std::vector< LatticeStateInfo > lat_state_info_
virtual bool GetArc(StateId s, Label ilabel, Arc *oarc)=0
Note: ilabel must not be epsilon.
std::vector< ComposedStateInfo > composed_state_info_
fst::DeterministicOnDemandFst< fst::StdArc > * det_fst_
fst::StdArc StdArc
kaldi::int32 int32
unordered_map< std::pair< int32, int32 >, int32, PairHasher< int32 > > pair_to_state_
LatticeWeightTpl< FloatType > Times(const LatticeWeightTpl< FloatType > &w1, const LatticeWeightTpl< FloatType > &w2)
float BaseFloat
Definition: kaldi-types.h:29
double ConvertToCost(const LatticeWeightTpl< Float > &w)
fst::StdArc::Weight Weight
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
fst::ArcTpl< CompactLatticeWeight > CompactLatticeArc
Definition: kaldi-lattice.h:42

◆ RecomputePruningInfo()

void RecomputePruningInfo ( )
private

Definition at line 420 of file compose-lattice-pruned.cc.

References PrunedCompactLatticeComposer::ComputeBackwardCosts(), PrunedCompactLatticeComposer::ComputeDeltaBackwardCosts(), PrunedCompactLatticeComposer::ComputeForwardCosts(), and PrunedCompactLatticeComposer::GetTopsortedStateList().

Referenced by PrunedCompactLatticeComposer::Compose(), and PrunedCompactLatticeComposer::ProcessQueueElement().

420  {
421  std::vector<int32> all_composed_states;
422  GetTopsortedStateList(&all_composed_states);
423  ComputeForwardCosts(all_composed_states);
424  ComputeBackwardCosts(all_composed_states);
425  ComputeDeltaBackwardCosts(all_composed_states);
426 }
void ComputeDeltaBackwardCosts(const std::vector< int32 > &composed_states)
void ComputeBackwardCosts(const std::vector< int32 > &composed_states)
void ComputeForwardCosts(const std::vector< int32 > &composed_states)
void GetTopsortedStateList(std::vector< int32 > *composed_states) const

Member Data Documentation

◆ accessed_lat_states_

◆ clat_in_

◆ clat_out_

◆ composed_state_info_

◆ composed_state_queue_

◆ current_cutoff_

◆ depth_penalty_

◆ det_fst_

◆ lat_best_cost_

◆ lat_state_info_

◆ num_arcs_out_

◆ opts_

◆ output_best_cost_

◆ output_reached_final_

bool output_reached_final_
private

◆ pair_to_state_

unordered_map<std::pair<int32,int32>, int32, PairHasher<int32> > pair_to_state_
private

The documentation for this class was generated from the following file: