|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <algorithm> |
|
#include <limits> |
|
#include <utility> |
|
|
|
#include "BitmapContainer.h" |
|
#include "HypothesisStackCubePruning.h" |
|
#include "moses/FF/DistortionScoreProducer.h" |
|
#include "TranslationOptionList.h" |
|
#include "Manager.h" |
|
|
|
namespace Moses |
|
{ |
|
|
|
class HypothesisScoreOrdererNoDistortion |
|
{ |
|
public: |
|
bool operator()(const Hypothesis* hypoA, const Hypothesis* hypoB) const { |
|
const float scoreA = hypoA->GetScore(); |
|
const float scoreB = hypoB->GetScore(); |
|
|
|
if (scoreA > scoreB) { |
|
return true; |
|
} else if (scoreA < scoreB) { |
|
return false; |
|
} else { |
|
return hypoA < hypoB; |
|
} |
|
} |
|
}; |
|
|
|
class HypothesisScoreOrdererWithDistortion |
|
{ |
|
private: |
|
bool m_deterministic; |
|
|
|
public: |
|
HypothesisScoreOrdererWithDistortion(const Range* transOptRange, |
|
const bool deterministic = false) |
|
: m_deterministic(deterministic) |
|
, m_transOptRange(transOptRange) { |
|
m_totalWeightDistortion = 0; |
|
const StaticData &staticData = StaticData::Instance(); |
|
|
|
const std::vector<const DistortionScoreProducer*> &ffs = DistortionScoreProducer::GetDistortionFeatureFunctions(); |
|
std::vector<const DistortionScoreProducer*>::const_iterator iter; |
|
for (iter = ffs.begin(); iter != ffs.end(); ++iter) { |
|
const DistortionScoreProducer *ff = *iter; |
|
|
|
float weight =staticData.GetAllWeights().GetScoreForProducer(ff); |
|
m_totalWeightDistortion += weight; |
|
} |
|
} |
|
|
|
const Range* m_transOptRange; |
|
float m_totalWeightDistortion; |
|
|
|
bool operator()(const Hypothesis* hypoA, const Hypothesis* hypoB) const { |
|
UTIL_THROW_IF2(m_transOptRange == NULL, "Words range not set"); |
|
|
|
|
|
const float distortionScoreA = DistortionScoreProducer::CalculateDistortionScore( |
|
*hypoA, |
|
hypoA->GetCurrSourceWordsRange(), |
|
*m_transOptRange, |
|
hypoA->GetWordsBitmap().GetFirstGapPos() |
|
); |
|
const float distortionScoreB = DistortionScoreProducer::CalculateDistortionScore( |
|
*hypoB, |
|
hypoB->GetCurrSourceWordsRange(), |
|
*m_transOptRange, |
|
hypoB->GetWordsBitmap().GetFirstGapPos() |
|
); |
|
|
|
|
|
const float scoreA = hypoA->GetScore() + distortionScoreA * m_totalWeightDistortion; |
|
const float scoreB = hypoB->GetScore() + distortionScoreB * m_totalWeightDistortion; |
|
|
|
|
|
if (scoreA > scoreB) { |
|
return true; |
|
} else if (scoreA < scoreB) { |
|
return false; |
|
} else { |
|
if (m_deterministic) { |
|
|
|
return (hypoA->GetCurrTargetPhrase().Compare(hypoB->GetCurrTargetPhrase()) < 0); |
|
} |
|
|
|
return hypoA < hypoB; |
|
} |
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
BackwardsEdge::BackwardsEdge(const BitmapContainer &prevBitmapContainer |
|
, BitmapContainer &parent |
|
, const TranslationOptionList &translations |
|
, const SquareMatrix &estimatedScores, |
|
const InputType& itype, |
|
const bool deterministic) |
|
: m_initialized(false) |
|
, m_prevBitmapContainer(prevBitmapContainer) |
|
, m_parent(parent) |
|
, m_translations(translations) |
|
, m_estimatedScores(estimatedScores) |
|
, m_deterministic(deterministic) |
|
, m_seenPosition() |
|
{ |
|
|
|
|
|
if(m_prevBitmapContainer.GetHypotheses().size() == 0 || m_translations.size() == 0) { |
|
VERBOSE(3, "Empty cube on BackwardsEdge" << std::endl); |
|
return; |
|
} |
|
|
|
|
|
|
|
int maxDistortion = itype.options()->reordering.max_distortion; |
|
|
|
if (maxDistortion == -1) { |
|
for (HypothesisSet::const_iterator iter = m_prevBitmapContainer.GetHypotheses().begin(); iter != m_prevBitmapContainer.GetHypotheses().end(); ++iter) { |
|
m_hypotheses.push_back(*iter); |
|
} |
|
return; |
|
} |
|
|
|
const Range &transOptRange = translations.Get(0)->GetSourceWordsRange(); |
|
|
|
HypothesisSet::const_iterator iterHypo = m_prevBitmapContainer.GetHypotheses().begin(); |
|
HypothesisSet::const_iterator iterEnd = m_prevBitmapContainer.GetHypotheses().end(); |
|
|
|
while (iterHypo != iterEnd) { |
|
const Hypothesis &hypo = **iterHypo; |
|
|
|
|
|
|
|
if (hypo.GetWordsBitmap().GetNumWordsCovered() == 0) { |
|
if ((int)transOptRange.GetStartPos() <= maxDistortion) |
|
m_hypotheses.push_back(&hypo); |
|
} else { |
|
int distortionDistance = itype.ComputeDistortionDistance(hypo.GetCurrSourceWordsRange() |
|
, transOptRange); |
|
|
|
if (distortionDistance <= maxDistortion) |
|
m_hypotheses.push_back(&hypo); |
|
} |
|
|
|
++iterHypo; |
|
} |
|
|
|
if (m_translations.size() > 1) { |
|
UTIL_THROW_IF2(m_translations.Get(0)->GetFutureScore() < m_translations.Get(1)->GetFutureScore(), |
|
"Non-monotonic future score: " |
|
<< m_translations.Get(0)->GetFutureScore() << " vs. " |
|
<< m_translations.Get(1)->GetFutureScore()); |
|
} |
|
|
|
if (m_hypotheses.size() > 1) { |
|
UTIL_THROW_IF2(m_hypotheses[0]->GetFutureScore() < m_hypotheses[1]->GetFutureScore(), |
|
"Non-monotonic total score" |
|
<< m_hypotheses[0]->GetFutureScore() << " vs. " |
|
<< m_hypotheses[1]->GetFutureScore()); |
|
} |
|
|
|
HypothesisScoreOrdererWithDistortion orderer (&transOptRange, m_deterministic); |
|
std::sort(m_hypotheses.begin(), m_hypotheses.end(), orderer); |
|
|
|
|
|
} |
|
|
|
BackwardsEdge::~BackwardsEdge() |
|
{ |
|
m_seenPosition.clear(); |
|
m_hypotheses.clear(); |
|
} |
|
|
|
|
|
void |
|
BackwardsEdge::Initialize() |
|
{ |
|
if(m_hypotheses.size() == 0 || m_translations.size() == 0) { |
|
m_initialized = true; |
|
return; |
|
} |
|
|
|
const Bitmap &bm = m_hypotheses[0]->GetWordsBitmap(); |
|
const Range &newRange = m_translations.Get(0)->GetSourceWordsRange(); |
|
m_estimatedScore = m_estimatedScores.CalcEstimatedScore(bm, newRange.GetStartPos(), newRange.GetEndPos()); |
|
|
|
Hypothesis *expanded = CreateHypothesis(*m_hypotheses[0], *m_translations.Get(0)); |
|
m_parent.Enqueue(0, 0, expanded, this); |
|
SetSeenPosition(0, 0); |
|
m_initialized = true; |
|
} |
|
|
|
Hypothesis *BackwardsEdge::CreateHypothesis(const Hypothesis &hypothesis, const TranslationOption &transOpt) |
|
{ |
|
|
|
IFVERBOSE(2) { |
|
hypothesis.GetManager().GetSentenceStats().StartTimeBuildHyp(); |
|
} |
|
const Bitmap &bitmap = m_parent.GetWordsBitmap(); |
|
Hypothesis *newHypo = new Hypothesis(hypothesis, transOpt, bitmap, hypothesis.GetManager().GetNextHypoId()); |
|
IFVERBOSE(2) { |
|
hypothesis.GetManager().GetSentenceStats().StopTimeBuildHyp(); |
|
} |
|
newHypo->EvaluateWhenApplied(m_estimatedScore); |
|
|
|
return newHypo; |
|
} |
|
|
|
bool |
|
BackwardsEdge::SeenPosition(const size_t x, const size_t y) |
|
{ |
|
boost::unordered_set< int >::iterator iter = m_seenPosition.find((x<<16) + y); |
|
return (iter != m_seenPosition.end()); |
|
} |
|
|
|
void |
|
BackwardsEdge::SetSeenPosition(const size_t x, const size_t y) |
|
{ |
|
UTIL_THROW_IF2(x >= (1<<17), "Error"); |
|
UTIL_THROW_IF2(y >= (1<<17), "Error"); |
|
|
|
m_seenPosition.insert((x<<16) + y); |
|
} |
|
|
|
|
|
bool |
|
BackwardsEdge::GetInitialized() |
|
{ |
|
return m_initialized; |
|
} |
|
|
|
const BitmapContainer& |
|
BackwardsEdge::GetBitmapContainer() const |
|
{ |
|
return m_prevBitmapContainer; |
|
} |
|
|
|
void |
|
BackwardsEdge::PushSuccessors(const size_t x, const size_t y) |
|
{ |
|
Hypothesis *newHypo; |
|
|
|
if(y + 1 < m_translations.size() && !SeenPosition(x, y + 1)) { |
|
SetSeenPosition(x, y + 1); |
|
newHypo = CreateHypothesis(*m_hypotheses[x], *m_translations.Get(y + 1)); |
|
if(newHypo != NULL) { |
|
m_parent.Enqueue(x, y + 1, newHypo, (BackwardsEdge*)this); |
|
} |
|
} |
|
|
|
if(x + 1 < m_hypotheses.size() && !SeenPosition(x + 1, y)) { |
|
SetSeenPosition(x + 1, y); |
|
newHypo = CreateHypothesis(*m_hypotheses[x + 1], *m_translations.Get(y)); |
|
if(newHypo != NULL) { |
|
m_parent.Enqueue(x + 1, y, newHypo, (BackwardsEdge*)this); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
BitmapContainer::BitmapContainer(const Bitmap &bitmap |
|
, HypothesisStackCubePruning &stack |
|
, bool deterministic) |
|
: m_bitmap(bitmap) |
|
, m_stack(stack) |
|
, m_numStackInsertions(0) |
|
, m_deterministic(deterministic) |
|
{ |
|
m_hypotheses = HypothesisSet(); |
|
m_edges = BackwardsEdgeSet(); |
|
m_queue = HypothesisQueue(); |
|
} |
|
|
|
BitmapContainer::~BitmapContainer() |
|
{ |
|
|
|
|
|
while (!m_queue.empty()) { |
|
HypothesisQueueItem *item = m_queue.top(); |
|
m_queue.pop(); |
|
|
|
delete item->GetHypothesis(); |
|
delete item; |
|
} |
|
|
|
|
|
RemoveAllInColl(m_edges); |
|
|
|
m_hypotheses.clear(); |
|
m_edges.clear(); |
|
} |
|
|
|
|
|
void |
|
BitmapContainer::Enqueue(int hypothesis_pos |
|
, int translation_pos |
|
, Hypothesis *hypothesis |
|
, BackwardsEdge *edge) |
|
{ |
|
|
|
const TargetPhrase *target_phrase = m_deterministic ? &(hypothesis->GetCurrTargetPhrase()) : NULL; |
|
HypothesisQueueItem *item = new HypothesisQueueItem(hypothesis_pos |
|
, translation_pos |
|
, hypothesis |
|
, edge |
|
, target_phrase); |
|
IFVERBOSE(2) { |
|
item->GetHypothesis()->GetManager().GetSentenceStats().StartTimeManageCubes(); |
|
} |
|
m_queue.push(item); |
|
IFVERBOSE(2) { |
|
item->GetHypothesis()->GetManager().GetSentenceStats().StopTimeManageCubes(); |
|
} |
|
} |
|
|
|
HypothesisQueueItem* |
|
BitmapContainer::Dequeue(bool keepValue) |
|
{ |
|
if (!m_queue.empty()) { |
|
HypothesisQueueItem *item = m_queue.top(); |
|
|
|
if (!keepValue) { |
|
m_queue.pop(); |
|
} |
|
|
|
return item; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
HypothesisQueueItem* |
|
BitmapContainer::Top() const |
|
{ |
|
return m_queue.top(); |
|
} |
|
|
|
size_t |
|
BitmapContainer::Size() |
|
{ |
|
return m_queue.size(); |
|
} |
|
|
|
bool |
|
BitmapContainer::Empty() const |
|
{ |
|
return m_queue.empty(); |
|
} |
|
|
|
const HypothesisSet& |
|
BitmapContainer::GetHypotheses() const |
|
{ |
|
return m_hypotheses; |
|
} |
|
|
|
size_t |
|
BitmapContainer::GetHypothesesSize() const |
|
{ |
|
return m_hypotheses.size(); |
|
} |
|
|
|
const BackwardsEdgeSet& |
|
BitmapContainer::GetBackwardsEdges() |
|
{ |
|
return m_edges; |
|
} |
|
|
|
void |
|
BitmapContainer::AddHypothesis(Hypothesis *hypothesis) |
|
{ |
|
bool itemExists = false; |
|
HypothesisSet::const_iterator iter = m_hypotheses.begin(); |
|
HypothesisSet::const_iterator iterEnd = m_hypotheses.end(); |
|
|
|
|
|
while (iter != iterEnd) { |
|
if (*iter == hypothesis) { |
|
itemExists = true; |
|
break; |
|
} |
|
|
|
++iter; |
|
} |
|
UTIL_THROW_IF2(itemExists, "Duplicate hypotheses"); |
|
m_hypotheses.push_back(hypothesis); |
|
} |
|
|
|
void |
|
BitmapContainer::AddBackwardsEdge(BackwardsEdge *edge) |
|
{ |
|
m_edges.insert(edge); |
|
} |
|
|
|
void |
|
BitmapContainer::InitializeEdges() |
|
{ |
|
BackwardsEdgeSet::iterator iter = m_edges.begin(); |
|
BackwardsEdgeSet::iterator iterEnd = m_edges.end(); |
|
|
|
while (iter != iterEnd) { |
|
BackwardsEdge *edge = *iter; |
|
edge->Initialize(); |
|
|
|
++iter; |
|
} |
|
} |
|
|
|
void |
|
BitmapContainer::EnsureMinStackHyps(const size_t minNumHyps) |
|
{ |
|
while ((!Empty()) && m_numStackInsertions < minNumHyps) { |
|
ProcessBestHypothesis(); |
|
} |
|
} |
|
|
|
void |
|
BitmapContainer::ProcessBestHypothesis() |
|
{ |
|
if (m_queue.empty()) { |
|
return; |
|
} |
|
|
|
|
|
HypothesisQueueItem *item = Dequeue(); |
|
|
|
|
|
UTIL_THROW_IF2(item == NULL, "Null object"); |
|
|
|
|
|
if (!Empty()) { |
|
HypothesisQueueItem *check = Dequeue(true); |
|
UTIL_THROW_IF2(item->GetHypothesis()->GetFutureScore() < check->GetHypothesis()->GetFutureScore(), |
|
"Non-monotonic total score: " |
|
<< item->GetHypothesis()->GetFutureScore() << " vs. " |
|
<< check->GetHypothesis()->GetFutureScore()); |
|
} |
|
|
|
|
|
IFVERBOSE(3) { |
|
item->GetHypothesis()->PrintHypothesis(); |
|
} |
|
|
|
|
|
const bool newstackentry = m_stack.AddPrune(item->GetHypothesis()); |
|
if (newstackentry) |
|
m_numStackInsertions++; |
|
|
|
IFVERBOSE(3) { |
|
TRACE_ERR("new stack entry flag is " << newstackentry << std::endl); |
|
} |
|
|
|
|
|
item->GetBackwardsEdge()->PushSuccessors(item->GetHypothesisPos(), item->GetTranslationPos()); |
|
|
|
|
|
delete item; |
|
} |
|
|
|
void |
|
BitmapContainer::SortHypotheses() |
|
{ |
|
std::sort(m_hypotheses.begin(), m_hypotheses.end(), HypothesisScoreOrderer(m_deterministic)); |
|
} |
|
|
|
} |
|
|
|
|