|
|
|
|
|
|
|
|
|
|
|
|
|
#include <boost/foreach.hpp> |
|
#include <cstdlib> |
|
#include <vector> |
|
#include <sstream> |
|
#include "../System.h" |
|
#include "../TranslationModel/PhraseTable.h" |
|
#include "Manager.h" |
|
#include "InputPath.h" |
|
#include "Hypothesis.h" |
|
#include "TargetPhraseImpl.h" |
|
#include "ActiveChart.h" |
|
#include "Sentence.h" |
|
|
|
#include "nbest/KBestExtractor.h" |
|
|
|
using namespace std; |
|
|
|
namespace Moses2 |
|
{ |
|
|
|
namespace SCFG |
|
{ |
|
|
|
Manager::Manager(System &sys, const TranslationTask &task, |
|
const std::string &inputStr, long translationId) |
|
:ManagerBase(sys, task, inputStr, translationId) |
|
{ |
|
|
|
} |
|
|
|
Manager::~Manager() |
|
{ |
|
|
|
} |
|
|
|
void Manager::Decode() |
|
{ |
|
|
|
|
|
InitPools(); |
|
|
|
|
|
FactorCollection &vocab = system.GetVocab(); |
|
m_input = Sentence::CreateFromString(GetPool(), vocab, system, m_inputStr, |
|
m_translationId); |
|
|
|
const SCFG::Sentence &sentence = static_cast<const SCFG::Sentence&>(GetInput()); |
|
|
|
size_t inputSize = sentence.GetSize(); |
|
|
|
|
|
m_inputPaths.Init(sentence, *this); |
|
|
|
|
|
m_stacks.Init(*this, inputSize); |
|
|
|
|
|
for (int startPos = inputSize - 1; startPos >= 0; --startPos) { |
|
|
|
SCFG::InputPath &initPath = *m_inputPaths.GetMatrix().GetValue(startPos, 0); |
|
|
|
|
|
InitActiveChart(initPath); |
|
|
|
|
|
int maxPhraseSize = inputSize - startPos + 1; |
|
for (int phraseSize = 1; phraseSize < maxPhraseSize; ++phraseSize) { |
|
|
|
|
|
SCFG::InputPath &path = *m_inputPaths.GetMatrix().GetValue(startPos, phraseSize); |
|
|
|
Stack &stack = m_stacks.GetStack(startPos, phraseSize); |
|
|
|
|
|
Lookup(path); |
|
|
|
Decode(path, stack); |
|
|
|
|
|
LookupUnary(path); |
|
|
|
|
|
|
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
void Manager::InitActiveChart(SCFG::InputPath &path) |
|
{ |
|
size_t numPt = system.mappings.size(); |
|
|
|
|
|
for (size_t i = 0; i < numPt; ++i) { |
|
const PhraseTable &pt = *system.mappings[i]; |
|
|
|
pt.InitActiveChart(GetPool(), *this, path); |
|
|
|
} |
|
} |
|
|
|
void Manager::Lookup(SCFG::InputPath &path) |
|
{ |
|
size_t numPt = system.mappings.size(); |
|
|
|
|
|
for (size_t i = 0; i < numPt; ++i) { |
|
const PhraseTable &pt = *system.mappings[i]; |
|
size_t maxChartSpan = system.maxChartSpans[i]; |
|
pt.Lookup(GetPool(), *this, maxChartSpan, m_stacks, path); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
void Manager::LookupUnary(SCFG::InputPath &path) |
|
{ |
|
size_t numPt = system.mappings.size(); |
|
|
|
|
|
for (size_t i = 0; i < numPt; ++i) { |
|
const PhraseTable &pt = *system.mappings[i]; |
|
pt.LookupUnary(GetPool(), *this, m_stacks, path); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Manager::Decode(SCFG::InputPath &path, Stack &stack) |
|
{ |
|
|
|
|
|
|
|
Recycler<HypothesisBase*> &hypoRecycler = GetHypoRecycle(); |
|
while (!m_queue.empty()) { |
|
QueueItem *item = m_queue.top(); |
|
m_queue.pop(); |
|
|
|
Hypothesis *hypo = item->hypo; |
|
hypoRecycler.Recycle(hypo); |
|
|
|
|
|
m_queueItemRecycler.push_back(item); |
|
} |
|
|
|
m_seenPositions.clear(); |
|
|
|
|
|
BOOST_FOREACH(const InputPath::Coll::value_type &valPair, path.targetPhrases) { |
|
const SymbolBind &symbolBind = valPair.first; |
|
const SCFG::TargetPhrases &tps = *valPair.second; |
|
|
|
CreateQueue(path, symbolBind, tps); |
|
} |
|
|
|
|
|
size_t pops = 0; |
|
while (!m_queue.empty() && pops < system.options.cube.pop_limit) { |
|
|
|
QueueItem *item = m_queue.top(); |
|
m_queue.pop(); |
|
|
|
|
|
Hypothesis *hypo = item->hypo; |
|
|
|
|
|
stack.Add(hypo, GetHypoRecycle(), arcLists); |
|
|
|
|
|
item->CreateNext(GetSystemPool(), GetPool(), *this, m_queue, m_seenPositions, path); |
|
|
|
m_queueItemRecycler.push_back(item); |
|
|
|
++pops; |
|
} |
|
|
|
} |
|
|
|
void Manager::CreateQueue( |
|
const SCFG::InputPath &path, |
|
const SymbolBind &symbolBind, |
|
const SCFG::TargetPhrases &tps) |
|
{ |
|
MemPool &pool = GetPool(); |
|
|
|
SeenPosition *seenItem = new (pool.Allocate<SeenPosition>()) SeenPosition(pool, symbolBind, tps, symbolBind.numNT); |
|
bool unseen = m_seenPositions.Add(seenItem); |
|
assert(unseen); |
|
|
|
QueueItem *item = QueueItem::Create(GetPool(), *this); |
|
item->Init(GetPool(), symbolBind, tps, seenItem->hypoIndColl); |
|
for (size_t i = 0; i < symbolBind.coll.size(); ++i) { |
|
const SymbolBindElement &ele = symbolBind.coll[i]; |
|
if (ele.hypos) { |
|
const Moses2::Hypotheses *hypos = ele.hypos; |
|
item->AddHypos(*hypos); |
|
} |
|
} |
|
|
|
item->CreateHypo(GetSystemPool(), *this, path, symbolBind); |
|
|
|
|
|
|
|
m_queue.push(item); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Manager::ExpandHypo( |
|
const SCFG::InputPath &path, |
|
const SCFG::SymbolBind &symbolBind, |
|
const SCFG::TargetPhraseImpl &tp, |
|
Stack &stack) |
|
{ |
|
Recycler<HypothesisBase*> &hypoRecycler = GetHypoRecycle(); |
|
|
|
std::vector<const SymbolBindElement*> ntEles = symbolBind.GetNTElements(); |
|
Vector<size_t> prevHyposIndices(GetPool(), symbolBind.numNT); |
|
assert(ntEles.size() == symbolBind.numNT); |
|
|
|
|
|
size_t ind = 0; |
|
while (IncrPrevHypoIndices(prevHyposIndices, ind, ntEles)) { |
|
SCFG::Hypothesis *hypo = SCFG::Hypothesis::Create(GetSystemPool(), *this); |
|
hypo->Init(*this, path, symbolBind, tp, prevHyposIndices); |
|
hypo->EvaluateWhenApplied(); |
|
|
|
stack.Add(hypo, hypoRecycler, arcLists); |
|
|
|
++ind; |
|
} |
|
} |
|
|
|
bool Manager::IncrPrevHypoIndices( |
|
Vector<size_t> &prevHyposIndices, |
|
size_t ind, |
|
const std::vector<const SymbolBindElement*> ntEles) |
|
{ |
|
if (ntEles.size() == 0) { |
|
|
|
return ind ? false : true; |
|
} |
|
|
|
size_t numHypos = 0; |
|
|
|
|
|
for (size_t i = 0; i < ntEles.size() - 1; ++i) { |
|
const SymbolBindElement &ele = *ntEles[i]; |
|
const Hypotheses &hypos = *ele.hypos; |
|
numHypos = hypos.size(); |
|
|
|
std::div_t divRet = std::div((int)ind, (int)numHypos); |
|
ind = divRet.quot; |
|
|
|
size_t hypoInd = divRet.rem; |
|
prevHyposIndices[i] = hypoInd; |
|
|
|
} |
|
|
|
|
|
prevHyposIndices.back() = ind; |
|
|
|
|
|
|
|
const SymbolBindElement &ele = *ntEles.back(); |
|
const Hypotheses &hypos = *ele.hypos; |
|
numHypos = hypos.size(); |
|
|
|
|
|
|
|
|
|
if (ind >= numHypos) { |
|
return false; |
|
} else { |
|
return true; |
|
} |
|
} |
|
|
|
std::string Manager::OutputBest() const |
|
{ |
|
string out; |
|
const Stack &lastStack = m_stacks.GetLastStack(); |
|
const SCFG::Hypothesis *bestHypo = lastStack.GetBestHypo(); |
|
|
|
if (bestHypo) { |
|
|
|
|
|
stringstream outStrm; |
|
Moses2::FixPrecision(outStrm); |
|
|
|
bestHypo->OutputToStream(outStrm); |
|
|
|
out = outStrm.str(); |
|
out = out.substr(4, out.size() - 10); |
|
|
|
if (system.options.output.ReportHypoScore) { |
|
out = SPrint(bestHypo->GetScores().GetTotalScore()) + " " + out; |
|
} |
|
} else { |
|
if (system.options.output.ReportHypoScore) { |
|
out = "0 "; |
|
} |
|
|
|
|
|
} |
|
|
|
return out; |
|
} |
|
|
|
std::string Manager::OutputNBest() |
|
{ |
|
stringstream out; |
|
|
|
|
|
arcLists.Sort(); |
|
|
|
|
|
KBestExtractor extractor(*this); |
|
extractor.OutputToStream(out); |
|
|
|
return out.str(); |
|
} |
|
|
|
std::string Manager::OutputTransOpt() |
|
{ |
|
const Stack &lastStack = m_stacks.GetLastStack(); |
|
const SCFG::Hypothesis *bestHypo = lastStack.GetBestHypo(); |
|
|
|
if (bestHypo) { |
|
stringstream outStrm; |
|
bestHypo->OutputTransOpt(outStrm); |
|
return outStrm.str(); |
|
} else { |
|
return ""; |
|
} |
|
} |
|
|
|
} |
|
} |
|
|
|
|