mirror of
https://github.com/moses-smt/mosesdecoder.git
synced 2024-12-28 14:32:38 +03:00
135 lines
4.2 KiB
C++
135 lines
4.2 KiB
C++
/***********************************************************************
|
|
Moses - statistical machine translation system
|
|
Copyright (C) 2006-2012 University of Edinburgh
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
***********************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include "IntermediateVarSpanNode.h"
|
|
#include "moses/WordsRange.h"
|
|
|
|
#include <boost/array.hpp>
|
|
|
|
#include <map>
|
|
|
|
#include <vector>
|
|
|
|
namespace Moses
|
|
{
|
|
|
|
/** @todo what is this?
|
|
*/
|
|
struct VarSpanNode
|
|
{
|
|
public:
|
|
struct NonTermRange {
|
|
size_t s1;
|
|
size_t s2;
|
|
size_t e1;
|
|
size_t e2;
|
|
};
|
|
typedef std::vector<IntermediateVarSpanNode> NodeVec;
|
|
typedef boost::array<int, 5> KeyType;
|
|
typedef std::map<KeyType, VarSpanNode> MapType;
|
|
|
|
VarSpanNode() : m_parent(0), m_label(0), m_rank(0) {}
|
|
|
|
VarSpanNode &Insert(const NodeVec &vec)
|
|
{
|
|
if (vec.empty()) {
|
|
return *this;
|
|
}
|
|
return Insert(vec.begin(), vec.end());
|
|
}
|
|
|
|
// Given a span, determine the ranges of possible start and end offsets
|
|
// for each non-terminal.
|
|
void CalculateRanges(int start, int end,
|
|
std::vector<NonTermRange> &ranges) const
|
|
{
|
|
ranges.resize(m_rank);
|
|
const VarSpanNode *n = this;
|
|
size_t firstIndex = m_rank;
|
|
while (n->m_parent) {
|
|
const KeyType &key = *(n->m_label);
|
|
assert(key[0] == 0 || key[0] == key[1]);
|
|
assert(key[3] == -1 || key[2] == key[3]);
|
|
const int numSplitPoints = key[4];
|
|
firstIndex -= numSplitPoints+1;
|
|
const int vsn_start = key[0] == 0 ? start : key[0];
|
|
const int vsn_end = key[3] == -1 ? end : key[3];
|
|
// The start position of the first non-terminal is known.
|
|
ranges[firstIndex].s1 = ranges[firstIndex].s2 = vsn_start - start;
|
|
// The end range depends on the number of split points. If there are
|
|
// no split points then the end position is fixed.
|
|
if (numSplitPoints) {
|
|
ranges[firstIndex].e1 = vsn_start - start;
|
|
ranges[firstIndex].e2 = vsn_end - start - numSplitPoints;
|
|
} else {
|
|
ranges[firstIndex].e1 = ranges[firstIndex].e2 = vsn_end - start;
|
|
}
|
|
// For the remaining non-terminals, the start and end boundaries shift
|
|
// by one position with each split point.
|
|
for (int i = 1; i <= numSplitPoints; ++i) {
|
|
ranges[firstIndex+i].s1 = ranges[firstIndex].s1+i;
|
|
ranges[firstIndex+i].s2 = ranges[firstIndex].e2+i;
|
|
ranges[firstIndex+i].e1 = ranges[firstIndex].s1+i;
|
|
ranges[firstIndex+i].e2 = ranges[firstIndex].e2+i;
|
|
}
|
|
// Except that the end point of the final non-terminal is fixed.
|
|
ranges[firstIndex+numSplitPoints].e1 = vsn_end - start;
|
|
ranges[firstIndex+numSplitPoints].e2 = vsn_end - start;
|
|
n = n->m_parent;
|
|
}
|
|
assert(firstIndex == 0);
|
|
}
|
|
|
|
const VarSpanNode *m_parent;
|
|
const KeyType *m_label;
|
|
size_t m_rank;
|
|
MapType m_children;
|
|
|
|
private:
|
|
VarSpanNode &Insert(NodeVec::const_iterator first,
|
|
NodeVec::const_iterator last)
|
|
{
|
|
assert(first != last);
|
|
|
|
KeyType key;
|
|
key[0] = first->m_start.first;
|
|
key[1] = first->m_start.second;
|
|
key[2] = first->m_end.first;
|
|
key[3] = first->m_end.second;
|
|
key[4] = first->m_numSplitPoints;
|
|
|
|
std::pair<MapType::iterator, bool> result = m_children.insert(
|
|
std::make_pair(key, VarSpanNode()));
|
|
VarSpanNode &child = result.first->second;
|
|
if (result.second) {
|
|
child.m_parent = this;
|
|
child.m_label = &(result.first->first);
|
|
child.m_rank = m_rank + first->m_numSplitPoints + 1;
|
|
}
|
|
if (++first == last) {
|
|
return child;
|
|
}
|
|
return child.Insert(first, last);
|
|
}
|
|
};
|
|
|
|
}
|