2012-07-18 17:52:48 +04:00
|
|
|
// vim:tabstop=2
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
Moses - factored phrase-based language decoder
|
|
|
|
Copyright (C) 2006 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
|
|
|
|
***********************************************************************/
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include <string>
|
|
|
|
#include <iterator>
|
|
|
|
#include <algorithm>
|
|
|
|
#include "RuleTable/Loader.h"
|
|
|
|
#include "RuleTable/LoaderFactory.h"
|
|
|
|
#include "PhraseDictionaryTMExtract.h"
|
|
|
|
#include "FactorCollection.h"
|
|
|
|
#include "Word.h"
|
|
|
|
#include "Util.h"
|
|
|
|
#include "InputFileStream.h"
|
|
|
|
#include "StaticData.h"
|
|
|
|
#include "WordsRange.h"
|
|
|
|
#include "UserMessage.h"
|
2012-07-19 20:56:46 +04:00
|
|
|
#include "CYKPlusParser/ChartRuleLookupManagerMemoryPerSentence.h"
|
2012-07-18 17:52:48 +04:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
namespace Moses
|
|
|
|
{
|
2012-07-18 20:59:21 +04:00
|
|
|
PhraseDictionaryTMExtract::PhraseDictionaryTMExtract(size_t numScoreComponents,
|
|
|
|
PhraseDictionaryFeature* feature)
|
2012-07-19 20:56:46 +04:00
|
|
|
: PhraseDictionary(numScoreComponents, feature)
|
2012-07-18 20:59:21 +04:00
|
|
|
{
|
|
|
|
const StaticData &staticData = StaticData::Instance();
|
|
|
|
CHECK(staticData.ThreadCount() == 1);
|
|
|
|
}
|
|
|
|
|
2012-07-23 17:31:05 +04:00
|
|
|
bool PhraseDictionaryTMExtract::Load(const std::vector<FactorType> &input
|
|
|
|
, const std::vector<FactorType> &output
|
|
|
|
, const std::string &filePath
|
|
|
|
, const std::vector<float> &weight
|
|
|
|
, size_t tableLimit,
|
|
|
|
const LMList& languageModels,
|
|
|
|
const WordPenaltyProducer* wpProducer)
|
|
|
|
{
|
|
|
|
m_languageModels = &(languageModels);
|
|
|
|
m_wpProducer = wpProducer;
|
|
|
|
m_tableLimit = tableLimit;
|
|
|
|
m_input = &input;
|
|
|
|
m_output = &output;
|
|
|
|
|
|
|
|
m_weight = &weight;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-07-19 22:36:46 +04:00
|
|
|
void PhraseDictionaryTMExtract::Initialize(const string &initStr)
|
|
|
|
{
|
|
|
|
cerr << "initStr=" << initStr << endl;
|
|
|
|
m_config = Tokenize(initStr, ";");
|
|
|
|
assert(m_config.size() == 4);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2012-07-18 17:52:48 +04:00
|
|
|
|
|
|
|
ChartRuleLookupManager *PhraseDictionaryTMExtract::CreateRuleLookupManager(
|
|
|
|
const InputType &sentence,
|
|
|
|
const ChartCellCollection &cellCollection)
|
|
|
|
{
|
2012-07-19 20:56:46 +04:00
|
|
|
return new ChartRuleLookupManagerMemoryPerSentence(sentence, cellCollection, *this);
|
2012-07-18 17:52:48 +04:00
|
|
|
}
|
2012-07-23 17:07:36 +04:00
|
|
|
|
|
|
|
void PhraseDictionaryTMExtract::InitializeForInput(InputType const& inputSentence)
|
2012-07-18 20:59:21 +04:00
|
|
|
{
|
2012-07-23 15:26:15 +04:00
|
|
|
/*
|
2012-07-19 22:36:46 +04:00
|
|
|
string data_root = "/tmp";
|
|
|
|
string in_file = data_root + "/in";
|
|
|
|
string pt_file = data_root + "/pt.out";
|
|
|
|
|
|
|
|
ofstream inFile(in_file.c_str());
|
|
|
|
|
|
|
|
for (size_t i = 1; i < source.GetSize() - 1; ++i)
|
|
|
|
{
|
2012-07-22 02:17:27 +04:00
|
|
|
inFile << source.GetWord(i);
|
2012-07-19 22:36:46 +04:00
|
|
|
}
|
|
|
|
inFile << endl;
|
|
|
|
inFile.close();
|
|
|
|
|
2012-07-18 20:59:21 +04:00
|
|
|
string cmd = "perl ~/workspace/github/hieuhoang/contrib/tm-mt-integration/make-pt-from-tm.perl "
|
2012-07-19 22:36:46 +04:00
|
|
|
+ in_file + " "
|
|
|
|
+ m_config[0] + " "
|
|
|
|
+ m_config[1] + " "
|
|
|
|
+ m_config[2] + " "
|
|
|
|
+ m_config[3] + " "
|
|
|
|
+ pt_file;
|
2012-07-22 02:17:27 +04:00
|
|
|
cerr << cmd << endl;
|
2012-07-19 22:36:46 +04:00
|
|
|
system(cmd.c_str());
|
|
|
|
|
|
|
|
cerr << "done\n";
|
2012-07-23 15:26:15 +04:00
|
|
|
*/
|
2012-07-18 20:59:21 +04:00
|
|
|
|
2012-07-23 15:26:15 +04:00
|
|
|
// populate with rules for this sentence
|
2012-07-23 17:07:36 +04:00
|
|
|
long translationId = inputSentence.GetTranslationId();
|
|
|
|
|
|
|
|
PhraseDictionaryNodeSCFG &rootNode = m_collection[translationId];
|
|
|
|
FormatType format = MosesFormat;
|
2012-07-23 15:26:15 +04:00
|
|
|
|
2012-07-23 17:18:49 +04:00
|
|
|
string grammarFile = "/tmp/pt.out.gz";
|
2012-07-23 15:26:15 +04:00
|
|
|
|
|
|
|
// data from file
|
|
|
|
InputFileStream inStream(grammarFile);
|
|
|
|
|
|
|
|
// copied from class LoaderStandard
|
|
|
|
PrintUserTime("Start loading new format pt model");
|
|
|
|
|
|
|
|
const StaticData &staticData = StaticData::Instance();
|
|
|
|
const std::string& factorDelimiter = staticData.GetFactorDelimiter();
|
|
|
|
|
|
|
|
|
|
|
|
string lineOrig;
|
|
|
|
size_t count = 0;
|
|
|
|
|
|
|
|
while(getline(inStream, lineOrig)) {
|
|
|
|
const string *line;
|
|
|
|
if (format == HieroFormat) { // reformat line
|
|
|
|
assert(false);
|
|
|
|
//line = ReformatHieroRule(lineOrig);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // do nothing to format of line
|
|
|
|
line = &lineOrig;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<string> tokens;
|
|
|
|
vector<float> scoreVector;
|
|
|
|
|
|
|
|
TokenizeMultiCharSeparator(tokens, *line , "|||" );
|
|
|
|
|
|
|
|
if (tokens.size() != 4 && tokens.size() != 5) {
|
|
|
|
stringstream strme;
|
|
|
|
strme << "Syntax error at " << grammarFile << ":" << count;
|
|
|
|
UserMessage::Add(strme.str());
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
const string &sourcePhraseString = tokens[0]
|
|
|
|
, &targetPhraseString = tokens[1]
|
|
|
|
, &scoreString = tokens[2]
|
|
|
|
, &alignString = tokens[3];
|
|
|
|
|
|
|
|
bool isLHSEmpty = (sourcePhraseString.find_first_not_of(" \t", 0) == string::npos);
|
|
|
|
if (isLHSEmpty && !staticData.IsWordDeletionEnabled()) {
|
|
|
|
TRACE_ERR( grammarFile << ":" << count << ": pt entry contains empty target, skipping\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Tokenize<float>(scoreVector, scoreString);
|
|
|
|
const size_t numScoreComponents = GetFeature()->GetNumScoreComponents();
|
|
|
|
if (scoreVector.size() != numScoreComponents) {
|
|
|
|
stringstream strme;
|
|
|
|
strme << "Size of scoreVector != number (" << scoreVector.size() << "!="
|
|
|
|
<< numScoreComponents << ") of score components on line " << count;
|
|
|
|
UserMessage::Add(strme.str());
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
CHECK(scoreVector.size() == numScoreComponents);
|
|
|
|
|
|
|
|
// parse source & find pt node
|
|
|
|
|
|
|
|
// constituent labels
|
|
|
|
Word sourceLHS, targetLHS;
|
|
|
|
|
|
|
|
// source
|
|
|
|
Phrase sourcePhrase( 0);
|
|
|
|
sourcePhrase.CreateFromStringNewFormat(Input, *m_input, sourcePhraseString, factorDelimiter, sourceLHS);
|
|
|
|
|
|
|
|
// create target phrase obj
|
|
|
|
TargetPhrase *targetPhrase = new TargetPhrase(Output);
|
|
|
|
targetPhrase->CreateFromStringNewFormat(Output, *m_output, targetPhraseString, factorDelimiter, targetLHS);
|
|
|
|
|
|
|
|
// rest of target phrase
|
|
|
|
targetPhrase->SetAlignmentInfo(alignString);
|
|
|
|
targetPhrase->SetTargetLHS(targetLHS);
|
|
|
|
//targetPhrase->SetDebugOutput(string("New Format pt ") + line);
|
|
|
|
|
|
|
|
// component score, for n-best output
|
|
|
|
std::transform(scoreVector.begin(),scoreVector.end(),scoreVector.begin(),TransformScore);
|
|
|
|
std::transform(scoreVector.begin(),scoreVector.end(),scoreVector.begin(),FloorScore);
|
|
|
|
|
2012-07-23 17:07:36 +04:00
|
|
|
targetPhrase->SetScoreChart(GetFeature(), scoreVector, *m_weight, *m_languageModels, m_wpProducer);
|
2012-07-23 15:26:15 +04:00
|
|
|
|
2012-07-23 17:07:36 +04:00
|
|
|
TargetPhraseCollection &phraseColl = GetOrCreateTargetPhraseCollection(rootNode, sourcePhrase, *targetPhrase, sourceLHS);
|
2012-07-23 15:26:15 +04:00
|
|
|
phraseColl.Add(targetPhrase);
|
|
|
|
|
|
|
|
count++;
|
|
|
|
|
|
|
|
if (format == HieroFormat) { // reformat line
|
|
|
|
delete line;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// sort and prune each target phrase collection
|
2012-07-23 17:07:36 +04:00
|
|
|
SortAndPrune(rootNode);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
TargetPhraseCollection &PhraseDictionaryTMExtract::GetOrCreateTargetPhraseCollection(PhraseDictionaryNodeSCFG &rootNode
|
|
|
|
, const Phrase &source
|
|
|
|
, const TargetPhrase &target
|
|
|
|
, const Word &sourceLHS)
|
|
|
|
{
|
|
|
|
PhraseDictionaryNodeSCFG &currNode = GetOrCreateNode(rootNode, source, target, sourceLHS);
|
|
|
|
return currNode.GetOrCreateTargetPhraseCollection();
|
|
|
|
}
|
|
|
|
|
|
|
|
PhraseDictionaryNodeSCFG &PhraseDictionaryTMExtract::GetOrCreateNode(PhraseDictionaryNodeSCFG &rootNode
|
|
|
|
, const Phrase &source
|
|
|
|
, const TargetPhrase &target
|
|
|
|
, const Word &sourceLHS)
|
|
|
|
{
|
2012-07-23 17:18:49 +04:00
|
|
|
cerr << source << endl << target << endl;
|
2012-07-23 17:07:36 +04:00
|
|
|
const size_t size = source.GetSize();
|
|
|
|
|
|
|
|
const AlignmentInfo &alignmentInfo = target.GetAlignmentInfo();
|
|
|
|
AlignmentInfo::const_iterator iterAlign = alignmentInfo.begin();
|
|
|
|
|
|
|
|
PhraseDictionaryNodeSCFG *currNode = &rootNode;
|
|
|
|
for (size_t pos = 0 ; pos < size ; ++pos) {
|
|
|
|
const Word& word = source.GetWord(pos);
|
|
|
|
|
|
|
|
if (word.IsNonTerminal()) {
|
|
|
|
// indexed by source label 1st
|
|
|
|
const Word &sourceNonTerm = word;
|
|
|
|
|
|
|
|
CHECK(iterAlign != target.GetAlignmentInfo().end());
|
|
|
|
CHECK(iterAlign->first == pos);
|
|
|
|
size_t targetNonTermInd = iterAlign->second;
|
|
|
|
++iterAlign;
|
|
|
|
const Word &targetNonTerm = target.GetWord(targetNonTermInd);
|
|
|
|
|
|
|
|
currNode = currNode->GetOrCreateChild(sourceNonTerm, targetNonTerm);
|
|
|
|
} else {
|
|
|
|
currNode = currNode->GetOrCreateChild(word);
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK(currNode != NULL);
|
|
|
|
}
|
2012-07-18 20:59:21 +04:00
|
|
|
|
2012-07-23 17:07:36 +04:00
|
|
|
// finally, the source LHS
|
|
|
|
//currNode = currNode->GetOrCreateChild(sourceLHS);
|
|
|
|
//CHECK(currNode != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
return *currNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhraseDictionaryTMExtract::SortAndPrune(PhraseDictionaryNodeSCFG &rootNode)
|
|
|
|
{
|
|
|
|
if (GetTableLimit())
|
|
|
|
{
|
|
|
|
rootNode.Sort(GetTableLimit());
|
|
|
|
}
|
2012-07-18 20:59:21 +04:00
|
|
|
}
|
|
|
|
|
2012-07-19 20:56:46 +04:00
|
|
|
void PhraseDictionaryTMExtract::CleanUp(const InputType &source)
|
2012-07-18 20:59:21 +04:00
|
|
|
{
|
2012-07-19 22:36:46 +04:00
|
|
|
m_collection.erase(source.GetTranslationId());
|
2012-07-19 21:59:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
const PhraseDictionaryNodeSCFG &PhraseDictionaryTMExtract::GetRootNode(const InputType &source) const
|
|
|
|
{
|
|
|
|
long transId = source.GetTranslationId();
|
|
|
|
std::map<long, PhraseDictionaryNodeSCFG>::const_iterator iter = m_collection.find(transId);
|
|
|
|
CHECK(iter != m_collection.end());
|
|
|
|
return iter->second;
|
|
|
|
}
|
|
|
|
PhraseDictionaryNodeSCFG &PhraseDictionaryTMExtract::GetRootNode(const InputType &source)
|
|
|
|
{
|
|
|
|
long transId = source.GetTranslationId();
|
|
|
|
std::map<long, PhraseDictionaryNodeSCFG>::iterator iter = m_collection.find(transId);
|
|
|
|
CHECK(iter != m_collection.end());
|
|
|
|
return iter->second;
|
2012-07-18 20:59:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-18 17:52:48 +04:00
|
|
|
TO_STRING_BODY(PhraseDictionaryTMExtract);
|
|
|
|
|
|
|
|
// friend
|
|
|
|
ostream& operator<<(ostream& out, const PhraseDictionaryTMExtract& phraseDict)
|
|
|
|
{
|
|
|
|
typedef PhraseDictionaryNodeSCFG::TerminalMap TermMap;
|
|
|
|
typedef PhraseDictionaryNodeSCFG::NonTerminalMap NonTermMap;
|
|
|
|
|
2012-07-19 21:59:50 +04:00
|
|
|
/*
|
2012-07-18 17:52:48 +04:00
|
|
|
const PhraseDictionaryNodeSCFG &coll = phraseDict.m_collection;
|
|
|
|
for (NonTermMap::const_iterator p = coll.m_nonTermMap.begin(); p != coll.m_nonTermMap.end(); ++p) {
|
|
|
|
const Word &sourceNonTerm = p->first.first;
|
|
|
|
out << sourceNonTerm;
|
|
|
|
}
|
|
|
|
for (TermMap::const_iterator p = coll.m_sourceTermMap.begin(); p != coll.m_sourceTermMap.end(); ++p) {
|
|
|
|
const Word &sourceTerm = p->first;
|
|
|
|
out << sourceTerm;
|
|
|
|
}
|
2012-07-19 21:59:50 +04:00
|
|
|
*/
|
|
|
|
|
2012-07-18 17:52:48 +04:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|