Program Listing for File hypothesis.h

Return to documentation for file (src/translator/hypothesis.h)

#pragma once
#include <memory>

#include "common/definitions.h"
#include "data/alignment.h"

namespace marian {

// one single (partial or full) hypothesis in beam search
// key elements:
//  - the word that this hyp ends with
//  - the aggregate score up to and including the word
//  - back pointer to previous hypothesis for traceback
class Hypothesis {
public:
  typedef IPtr<Hypothesis> PtrType;

private:
  // Constructors are private, use Hypothesis::New(...)

  Hypothesis() : prevHyp_(nullptr), prevBeamHypIdx_(0), word_(Word::ZERO), pathScore_(0.0) {}

  Hypothesis(const PtrType prevHyp,
             Word word,
             size_t prevBeamHypIdx, // beam-hyp index that this hypothesis originated from
             float pathScore)
      : prevHyp_(prevHyp), prevBeamHypIdx_(prevBeamHypIdx), word_(word), pathScore_(pathScore) {}

public:
 // Use this whenever creating a pointer to MemoryPiece
 template <class ...Args>
 static PtrType New(Args&& ...args) {
   return PtrType(new Hypothesis(std::forward<Args>(args)...));
 }

  const PtrType getPrevHyp() const { return prevHyp_; }

  Word getWord() const { return word_; }

  size_t getPrevStateIndex() const { return prevBeamHypIdx_; }

  float getPathScore() const { return pathScore_; }

  const std::vector<float>& getScoreBreakdown() { return scoreBreakdown_; }
  void setScoreBreakdown(const std::vector<float>& scoreBreakdown) { scoreBreakdown_ = scoreBreakdown; }

  const std::vector<float>& getAlignment() { return alignment_; }
  void setAlignment(const std::vector<float>& align) { alignment_ = align; };

  // trace back paths referenced from this hypothesis
  Words tracebackWords() {
    Words targetWords;
    for(auto hyp = this; hyp->getPrevHyp(); hyp = hyp->getPrevHyp().get()) {
      targetWords.push_back(hyp->getWord());
    }
    std::reverse(targetWords.begin(), targetWords.end());
    return targetWords;
  }

  // calculate word-level scores for each target word by de-aggregating the path score
  std::vector<float> tracebackWordScores() {
    std::vector<float> scores;
    // traverse hypotheses backward
    for(auto hyp = this; hyp->getPrevHyp(); hyp = hyp->getPrevHyp().get()) {
      // a path score is a cumulative score including scores from all preceding hypotheses (words),
      // so calculate a word-level score by subtracting the previous path score from the current path score
      auto prevPathScore = hyp->getPrevHyp() ? hyp->getPrevHyp().get()->pathScore_ : 0.f;
      scores.push_back(hyp->pathScore_ - prevPathScore);
    }
    std::reverse(scores.begin(), scores.end());
    return scores;
  }

  // get soft alignments [t][s] -> P(s|t) for each target word starting from the hyp one
  typedef data::SoftAlignment SoftAlignment;
  SoftAlignment tracebackAlignment() {
    SoftAlignment align;
    for(auto hyp = this; hyp->getPrevHyp(); hyp = hyp->getPrevHyp().get()) {
      align.push_back(hyp->getAlignment());
    }
    std::reverse(align.begin(), align.end());
    return align;  // [t][s] -> P(s|t)
  }

private:
  const PtrType prevHyp_;
  const size_t prevBeamHypIdx_;
  const Word word_;
  const float pathScore_;

  std::vector<float> scoreBreakdown_; // [num scorers]
  std::vector<float> alignment_;

  ENABLE_INTRUSIVE_PTR(Hypothesis)
};

typedef std::vector<IPtr<Hypothesis>> Beam;                // Beam = vector [beamSize] of hypotheses
typedef std::vector<Beam> Beams;                          // Beams = vector [batchDim] of vector [beamSize] of hypotheses
typedef std::tuple<Words, IPtr<Hypothesis>, float> Result; // (word ids for hyp, hyp, normalized sentence score for hyp)
typedef std::vector<Result> NBestList;                    // sorted vector of (word ids, hyp, sent score) tuples
}  // namespace marian