Welcome to mirror list, hosted at ThFree Co, Russian Federation.

SearchNormalBatch.cpp « moses - github.com/moses-smt/mosesdecoder.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 612a5deea8e215b174a7bdec00af4feb9dfc66eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#include "SearchNormalBatch.h"
#include "LM/Base.h"
#include "Manager.h"
#include "Hypothesis.h"
#include "util/exception.hh"

//#include <google/profiler.h>

using namespace std;

namespace Moses
{
SearchNormalBatch::SearchNormalBatch(Manager& manager, const InputType &source, const TranslationOptionCollection &transOptColl)
  :SearchNormal(manager, source, transOptColl)
  ,m_batch_size(10000)
{
  m_max_stack_size = StaticData::Instance().GetMaxHypoStackSize();

  // Split the feature functions into sets of stateless, stateful
  // distributed lm, and stateful non-distributed.
  const vector<const StatefulFeatureFunction*>& ffs =
    StatefulFeatureFunction::GetStatefulFeatureFunctions();
  for (unsigned i = 0; i < ffs.size(); ++i) {
    if (ffs[i]->GetScoreProducerDescription() == "DLM_5gram") { // TODO WFT
      m_dlm_ffs[i] = const_cast<LanguageModel*>(static_cast<const LanguageModel* const>(ffs[i]));
      m_dlm_ffs[i]->SetFFStateIdx(i);
    } else {
      m_stateful_ffs[i] = const_cast<StatefulFeatureFunction*>(ffs[i]);
    }
  }
  m_stateless_ffs = StatelessFeatureFunction::GetStatelessFeatureFunctions();

}

SearchNormalBatch::~SearchNormalBatch()
{
}

/**
 * Main decoder loop that translates a sentence by expanding
 * hypotheses stack by stack, until the end of the sentence.
 */
void SearchNormalBatch::Decode()
{
  const StaticData &staticData = StaticData::Instance();
  SentenceStats &stats = m_manager.GetSentenceStats();

  // initial seed hypothesis: nothing translated, no words produced
  Hypothesis *hypo = Hypothesis::Create(m_manager,m_source, m_initialTransOpt);
  m_hypoStackColl[0]->AddPrune(hypo);

  // go through each stack
  std::vector < HypothesisStack* >::iterator iterStack;
  for (iterStack = m_hypoStackColl.begin() ; iterStack != m_hypoStackColl.end() ; ++iterStack) {
    // check if decoding ran out of time
    double _elapsed_time = GetUserTime();
    if (_elapsed_time > staticData.GetTimeoutThreshold()) {
      VERBOSE(1,"Decoding is out of time (" << _elapsed_time << "," << staticData.GetTimeoutThreshold() << ")" << std::endl);
      interrupted_flag = 1;
      return;
    }
    HypothesisStackNormal &sourceHypoColl = *static_cast<HypothesisStackNormal*>(*iterStack);

    // the stack is pruned before processing (lazy pruning):
    VERBOSE(3,"processing hypothesis from next stack");
    IFVERBOSE(2) {
      stats.StartTimeStack();
    }
    sourceHypoColl.PruneToSize(staticData.GetMaxHypoStackSize());
    VERBOSE(3,std::endl);
    sourceHypoColl.CleanupArcList();
    IFVERBOSE(2) {
      stats.StopTimeStack();
    }

    // go through each hypothesis on the stack and try to expand it
    HypothesisStackNormal::const_iterator iterHypo;
    for (iterHypo = sourceHypoColl.begin() ; iterHypo != sourceHypoColl.end() ; ++iterHypo) {
      Hypothesis &hypothesis = **iterHypo;
      ProcessOneHypothesis(hypothesis); // expand the hypothesis
    }
    EvalAndMergePartialHypos();

    // some logging
    IFVERBOSE(2) {
      OutputHypoStackSize();
    }

    // this stack is fully expanded;
    actual_hypoStack = &sourceHypoColl;
  }

  EvalAndMergePartialHypos();
}

/**
 * Expand one hypothesis with a translation option.
 * this involves initial creation, scoring and adding it to the proper stack
 * \param hypothesis hypothesis to be expanded upon
 * \param transOpt translation option (phrase translation)
 *        that is applied to create the new hypothesis
 * \param expectedScore base score for early discarding
 *        (base hypothesis score plus future score estimation)
 */

void
SearchNormalBatch::
ExpandHypothesis(const Hypothesis &hypothesis,
                 const TranslationOption &transOpt, float expectedScore)
{
  // Check if the number of partial hypotheses exceeds the batch size.
  if (m_partial_hypos.size() >= m_batch_size) {
    EvalAndMergePartialHypos();
  }

  const StaticData &staticData = StaticData::Instance();
  SentenceStats &stats = m_manager.GetSentenceStats();

  Hypothesis *newHypo;
  if (! staticData.UseEarlyDiscarding()) {
    // simple build, no questions asked
    IFVERBOSE(2) {
      stats.StartTimeBuildHyp();
    }
    newHypo = hypothesis.CreateNext(transOpt);
    IFVERBOSE(2) {
      stats.StopTimeBuildHyp();
    }
    if (newHypo==NULL) return;
    //newHypo->Evaluate(m_transOptColl.GetFutureScore());

    // Issue DLM requests for new hypothesis and put into the list of
    // partial hypotheses.
    std::map<int, LanguageModel*>::iterator dlm_iter;
    for (dlm_iter = m_dlm_ffs.begin();
         dlm_iter != m_dlm_ffs.end();
         ++dlm_iter) {
      const FFState* input_state = newHypo->GetPrevHypo() ? newHypo->GetPrevHypo()->GetFFState((*dlm_iter).first) : NULL;
      (*dlm_iter).second->IssueRequestsFor(*newHypo, input_state);
    }
    m_partial_hypos.push_back(newHypo);
  } else {
    UTIL_THROW2("can't use early discarding with batch decoding!");
  }
}

void SearchNormalBatch::EvalAndMergePartialHypos()
{
  std::vector<Hypothesis*>::iterator partial_hypo_iter;
  for (partial_hypo_iter = m_partial_hypos.begin();
       partial_hypo_iter != m_partial_hypos.end();
       ++partial_hypo_iter) {
    Hypothesis* hypo = *partial_hypo_iter;

    // Evaluate with other ffs.
    std::map<int, StatefulFeatureFunction*>::iterator sfff_iter;
    for (sfff_iter = m_stateful_ffs.begin();
         sfff_iter != m_stateful_ffs.end();
         ++sfff_iter) {
      const StatefulFeatureFunction &ff = *(sfff_iter->second);
      int state_idx = sfff_iter->first;
      hypo->EvaluateWhenApplied(ff, state_idx);
    }
    std::vector<const StatelessFeatureFunction*>::iterator slff_iter;
    for (slff_iter = m_stateless_ffs.begin();
         slff_iter != m_stateless_ffs.end();
         ++slff_iter) {
      hypo->EvaluateWhenApplied(**slff_iter);
    }
  }

  // Wait for all requests from the distributed LM to come back.
  std::map<int, LanguageModel*>::iterator dlm_iter;
  for (dlm_iter = m_dlm_ffs.begin();
       dlm_iter != m_dlm_ffs.end();
       ++dlm_iter) {
    (*dlm_iter).second->sync();
  }

  // Incorporate the DLM scores into all hypotheses and put into their
  // stacks.
  for (partial_hypo_iter = m_partial_hypos.begin();
       partial_hypo_iter != m_partial_hypos.end();
       ++partial_hypo_iter) {
    Hypothesis* hypo = *partial_hypo_iter;

    // Calculate DLM scores.
    std::map<int, LanguageModel*>::iterator dlm_iter;
    for (dlm_iter = m_dlm_ffs.begin();
         dlm_iter != m_dlm_ffs.end();
         ++dlm_iter) {
      LanguageModel &lm = *(dlm_iter->second);
      hypo->EvaluateWhenApplied(lm, (*dlm_iter).first);
    }

    // Put completed hypothesis onto its stack.
    size_t wordsTranslated = hypo->GetWordsBitmap().GetNumWordsCovered();
    m_hypoStackColl[wordsTranslated]->AddPrune(hypo);
  }
  m_partial_hypos.clear();

  std::vector < HypothesisStack* >::iterator stack_iter;
  HypothesisStackNormal* stack;
  for (stack_iter = m_hypoStackColl.begin();
       stack_iter != m_hypoStackColl.end();
       ++stack_iter) {
    stack = static_cast<HypothesisStackNormal*>(*stack_iter);
    stack->PruneToSize(m_max_stack_size);
  }
}

}