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
|
|
|
|
***********************************************************************/
|
|
|
|
|
2012-10-08 23:52:27 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
|
2012-07-18 17:52:48 +04:00
|
|
|
#include <fstream>
|
|
|
|
#include <string>
|
|
|
|
#include <iterator>
|
|
|
|
#include <algorithm>
|
2012-11-12 23:56:18 +04:00
|
|
|
#include "Loader.h"
|
|
|
|
#include "LoaderFactory.h"
|
2012-08-14 02:53:14 +04:00
|
|
|
#include "PhraseDictionaryFuzzyMatch.h"
|
2012-11-12 23:56:18 +04:00
|
|
|
#include "moses/FactorCollection.h"
|
|
|
|
#include "moses/Word.h"
|
|
|
|
#include "moses/Util.h"
|
|
|
|
#include "moses/InputFileStream.h"
|
|
|
|
#include "moses/StaticData.h"
|
|
|
|
#include "moses/WordsRange.h"
|
|
|
|
#include "moses/UserMessage.h"
|
2012-08-07 00:41:24 +04:00
|
|
|
#include "util/file.hh"
|
2012-11-27 21:23:31 +04:00
|
|
|
#include "moses/TranslationModel/CYKPlusParser/ChartRuleLookupManagerMemoryPerSentence.h"
|
2012-07-18 17:52:48 +04:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
namespace Moses
|
|
|
|
{
|
2012-07-27 03:10:49 +04:00
|
|
|
|
2013-02-22 23:17:57 +04:00
|
|
|
PhraseDictionaryFuzzyMatch::PhraseDictionaryFuzzyMatch(const std::string &line)
|
|
|
|
: PhraseDictionary("PhraseDictionaryFuzzyMatch", line)
|
|
|
|
{}
|
2012-07-18 20:59:21 +04:00
|
|
|
|
2012-08-14 02:53:14 +04:00
|
|
|
bool PhraseDictionaryFuzzyMatch::Load(const std::vector<FactorType> &input
|
2012-07-23 17:31:05 +04:00
|
|
|
, const std::vector<FactorType> &output
|
2012-07-23 19:36:39 +04:00
|
|
|
, const std::string &initStr
|
2013-05-21 16:39:31 +04:00
|
|
|
, size_t tableLimit)
|
2012-07-23 17:31:05 +04:00
|
|
|
{
|
|
|
|
m_tableLimit = tableLimit;
|
|
|
|
m_input = &input;
|
|
|
|
m_output = &output;
|
|
|
|
|
2012-07-23 19:36:39 +04:00
|
|
|
|
2012-07-19 22:36:46 +04:00
|
|
|
cerr << "initStr=" << initStr << endl;
|
|
|
|
m_config = Tokenize(initStr, ";");
|
2012-07-31 05:21:48 +04:00
|
|
|
assert(m_config.size() == 3);
|
2012-07-23 19:36:39 +04:00
|
|
|
|
2012-08-14 02:53:14 +04:00
|
|
|
m_FuzzyMatchWrapper = new tmmt::FuzzyMatchWrapper(m_config[0], m_config[1], m_config[2]);
|
2012-07-31 00:07:19 +04:00
|
|
|
|
2012-07-23 19:36:39 +04:00
|
|
|
return true;
|
2012-07-19 22:36:46 +04:00
|
|
|
}
|
2012-07-18 17:52:48 +04:00
|
|
|
|
2012-08-14 02:53:14 +04:00
|
|
|
ChartRuleLookupManager *PhraseDictionaryFuzzyMatch::CreateRuleLookupManager(
|
2012-07-18 17:52:48 +04:00
|
|
|
const InputType &sentence,
|
2012-10-11 17:27:30 +04:00
|
|
|
const ChartCellCollectionBase &cellCollection)
|
2012-07-18 17:52:48 +04:00
|
|
|
{
|
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
|
|
|
|
2012-10-08 23:52:27 +04:00
|
|
|
|
|
|
|
int removedirectoryrecursively(const char *dirname)
|
|
|
|
{
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *entry;
|
|
|
|
char path[PATH_MAX];
|
|
|
|
|
|
|
|
if (path == NULL) {
|
|
|
|
fprintf(stderr, "Out of memory error\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
dir = opendir(dirname);
|
|
|
|
if (dir == NULL) {
|
|
|
|
perror("Error opendir()");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((entry = readdir(dir)) != NULL) {
|
|
|
|
if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
|
|
|
|
snprintf(path, (size_t) PATH_MAX, "%s/%s", dirname, entry->d_name);
|
|
|
|
if (entry->d_type == DT_DIR) {
|
|
|
|
removedirectoryrecursively(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
remove(path);
|
|
|
|
/*
|
|
|
|
* Here, the actual deletion must be done. Beacuse this is
|
|
|
|
* quite a dangerous thing to do, and this program is not very
|
|
|
|
* well tested, we are just printing as if we are deleting.
|
|
|
|
*/
|
|
|
|
//printf("(not really) Deleting: %s\n", path);
|
|
|
|
/*
|
|
|
|
* When you are finished testing this and feel you are ready to do the real
|
|
|
|
* deleting, use this: remove*STUB*(path);
|
|
|
|
* (see "man 3 remove")
|
|
|
|
* Please note that I DONT TAKE RESPONSIBILITY for data you delete with this!
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
closedir(dir);
|
|
|
|
|
|
|
|
rmdir(dirname);
|
|
|
|
/*
|
|
|
|
* Now the directory is emtpy, finally delete the directory itself. (Just
|
|
|
|
* printing here, see above)
|
|
|
|
*/
|
|
|
|
//printf("(not really) Deleting: %s\n", dirname);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-08-14 02:53:14 +04:00
|
|
|
void PhraseDictionaryFuzzyMatch::InitializeForInput(InputType const& inputSentence)
|
2012-07-18 20:59:21 +04:00
|
|
|
{
|
2012-10-09 15:06:14 +04:00
|
|
|
char dirName[] = "/tmp/moses.XXXXXX";
|
2012-10-08 23:52:27 +04:00
|
|
|
char *temp = mkdtemp(dirName);
|
|
|
|
CHECK(temp);
|
|
|
|
string dirNameStr(dirName);
|
|
|
|
|
|
|
|
string inFileName(dirNameStr + "/in");
|
2012-07-19 22:36:46 +04:00
|
|
|
|
2012-07-31 05:21:48 +04:00
|
|
|
ofstream inFile(inFileName.c_str());
|
2012-07-19 22:36:46 +04:00
|
|
|
|
2012-07-23 18:10:15 +04:00
|
|
|
for (size_t i = 1; i < inputSentence.GetSize() - 1; ++i)
|
2012-07-19 22:36:46 +04:00
|
|
|
{
|
2012-07-23 18:10:15 +04:00
|
|
|
inFile << inputSentence.GetWord(i);
|
2012-07-19 22:36:46 +04:00
|
|
|
}
|
|
|
|
inFile << endl;
|
|
|
|
inFile.close();
|
2012-08-07 00:41:24 +04:00
|
|
|
|
2012-07-23 17:07:36 +04:00
|
|
|
long translationId = inputSentence.GetTranslationId();
|
2012-11-27 14:42:28 +04:00
|
|
|
string ptFileName = m_FuzzyMatchWrapper->Extract(translationId, dirNameStr);
|
2012-07-23 17:07:36 +04:00
|
|
|
|
2012-11-27 14:42:28 +04:00
|
|
|
// populate with rules for this sentence
|
2013-05-24 19:33:30 +04:00
|
|
|
PhraseDictionaryNodeMemory &rootNode = m_collection[translationId];
|
2012-07-23 17:07:36 +04:00
|
|
|
FormatType format = MosesFormat;
|
2012-07-31 02:49:13 +04:00
|
|
|
|
2012-07-23 15:26:15 +04:00
|
|
|
// data from file
|
2012-07-31 05:21:48 +04:00
|
|
|
InputFileStream inStream(ptFileName);
|
2012-07-23 15:26:15 +04:00
|
|
|
|
|
|
|
// copied from class LoaderStandard
|
2012-08-09 15:47:48 +04:00
|
|
|
PrintUserTime("Start loading fuzzy-match phrase model");
|
2012-07-23 15:26:15 +04:00
|
|
|
|
|
|
|
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;
|
2012-07-31 05:21:48 +04:00
|
|
|
strme << "Syntax error at " << ptFileName << ":" << count;
|
2012-07-23 15:26:15 +04:00
|
|
|
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()) {
|
2012-07-31 05:21:48 +04:00
|
|
|
TRACE_ERR( ptFileName << ":" << count << ": pt entry contains empty target, skipping\n");
|
2012-07-23 15:26:15 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Tokenize<float>(scoreVector, scoreString);
|
2013-02-22 23:17:57 +04:00
|
|
|
const size_t numScoreComponents = GetNumScoreComponents();
|
2012-07-23 15:26:15 +04:00
|
|
|
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
|
2013-05-22 17:41:28 +04:00
|
|
|
Word *sourceLHS;
|
|
|
|
Word *targetLHS;
|
2012-07-23 15:26:15 +04:00
|
|
|
|
|
|
|
// source
|
|
|
|
Phrase sourcePhrase( 0);
|
2013-03-09 02:04:28 +04:00
|
|
|
sourcePhrase.CreateFromString(Input, *m_input, sourcePhraseString, factorDelimiter, &sourceLHS);
|
2012-07-23 15:26:15 +04:00
|
|
|
|
|
|
|
// create target phrase obj
|
2012-10-22 20:40:23 +04:00
|
|
|
TargetPhrase *targetPhrase = new TargetPhrase();
|
2013-05-22 15:28:32 +04:00
|
|
|
targetPhrase->CreateFromString(Output, *m_output, targetPhraseString, factorDelimiter, &targetLHS);
|
2012-07-23 15:26:15 +04:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
2013-05-13 18:36:09 +04:00
|
|
|
targetPhrase->GetScoreBreakdown().Assign(this, scoreVector);
|
2013-05-28 03:41:25 +04:00
|
|
|
targetPhrase->Evaluate(sourcePhrase);
|
2012-07-23 15:26:15 +04:00
|
|
|
|
2013-05-22 18:00:32 +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);
|
2012-07-23 18:10:15 +04:00
|
|
|
|
2012-10-23 20:07:28 +04:00
|
|
|
//removedirectoryrecursively(dirName);
|
2012-07-23 17:07:36 +04:00
|
|
|
}
|
|
|
|
|
2013-05-24 19:33:30 +04:00
|
|
|
TargetPhraseCollection &PhraseDictionaryFuzzyMatch::GetOrCreateTargetPhraseCollection(PhraseDictionaryNodeMemory &rootNode
|
2012-07-23 17:07:36 +04:00
|
|
|
, const Phrase &source
|
|
|
|
, const TargetPhrase &target
|
2013-05-22 18:00:32 +04:00
|
|
|
, const Word *sourceLHS)
|
2012-07-23 17:07:36 +04:00
|
|
|
{
|
2013-05-24 19:33:30 +04:00
|
|
|
PhraseDictionaryNodeMemory &currNode = GetOrCreateNode(rootNode, source, target, sourceLHS);
|
2012-07-23 17:07:36 +04:00
|
|
|
return currNode.GetOrCreateTargetPhraseCollection();
|
|
|
|
}
|
|
|
|
|
2013-05-24 19:33:30 +04:00
|
|
|
PhraseDictionaryNodeMemory &PhraseDictionaryFuzzyMatch::GetOrCreateNode(PhraseDictionaryNodeMemory &rootNode
|
2012-07-23 17:07:36 +04:00
|
|
|
, const Phrase &source
|
|
|
|
, const TargetPhrase &target
|
2013-05-22 18:00:32 +04:00
|
|
|
, const Word *sourceLHS)
|
2012-07-23 17:07:36 +04:00
|
|
|
{
|
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();
|
|
|
|
|
2012-10-19 18:10:10 +04:00
|
|
|
const AlignmentInfo &alignmentInfo = target.GetAlignNonTerm();
|
2012-07-23 17:07:36 +04:00
|
|
|
AlignmentInfo::const_iterator iterAlign = alignmentInfo.begin();
|
|
|
|
|
2013-05-24 19:33:30 +04:00
|
|
|
PhraseDictionaryNodeMemory *currNode = &rootNode;
|
2012-07-23 17:07:36 +04:00
|
|
|
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;
|
|
|
|
|
2012-10-19 18:10:10 +04:00
|
|
|
CHECK(iterAlign != alignmentInfo.end());
|
2012-07-23 17:07:36 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-05-24 19:33:30 +04:00
|
|
|
void PhraseDictionaryFuzzyMatch::SortAndPrune(PhraseDictionaryNodeMemory &rootNode)
|
2012-07-23 17:07:36 +04:00
|
|
|
{
|
|
|
|
if (GetTableLimit())
|
|
|
|
{
|
|
|
|
rootNode.Sort(GetTableLimit());
|
|
|
|
}
|
2012-07-18 20:59:21 +04:00
|
|
|
}
|
|
|
|
|
2012-12-24 19:37:11 +04:00
|
|
|
void PhraseDictionaryFuzzyMatch::CleanUpAfterSentenceProcessing(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
|
|
|
}
|
|
|
|
|
2013-05-24 19:33:30 +04:00
|
|
|
const PhraseDictionaryNodeMemory &PhraseDictionaryFuzzyMatch::GetRootNode(const InputType &source) const
|
2012-07-19 21:59:50 +04:00
|
|
|
{
|
|
|
|
long transId = source.GetTranslationId();
|
2013-05-24 19:33:30 +04:00
|
|
|
std::map<long, PhraseDictionaryNodeMemory>::const_iterator iter = m_collection.find(transId);
|
2012-07-19 21:59:50 +04:00
|
|
|
CHECK(iter != m_collection.end());
|
|
|
|
return iter->second;
|
|
|
|
}
|
2013-05-24 19:33:30 +04:00
|
|
|
PhraseDictionaryNodeMemory &PhraseDictionaryFuzzyMatch::GetRootNode(const InputType &source)
|
2012-07-19 21:59:50 +04:00
|
|
|
{
|
|
|
|
long transId = source.GetTranslationId();
|
2013-05-24 19:33:30 +04:00
|
|
|
std::map<long, PhraseDictionaryNodeMemory>::iterator iter = m_collection.find(transId);
|
2012-07-19 21:59:50 +04:00
|
|
|
CHECK(iter != m_collection.end());
|
|
|
|
return iter->second;
|
2012-07-18 20:59:21 +04:00
|
|
|
}
|
2012-07-27 03:10:49 +04:00
|
|
|
|
2012-08-14 02:53:14 +04:00
|
|
|
TO_STRING_BODY(PhraseDictionaryFuzzyMatch);
|
2012-07-18 17:52:48 +04:00
|
|
|
|
|
|
|
// friend
|
2012-08-14 02:53:14 +04:00
|
|
|
ostream& operator<<(ostream& out, const PhraseDictionaryFuzzyMatch& phraseDict)
|
2012-07-18 17:52:48 +04:00
|
|
|
{
|
2013-05-24 19:33:30 +04:00
|
|
|
typedef PhraseDictionaryNodeMemory::TerminalMap TermMap;
|
|
|
|
typedef PhraseDictionaryNodeMemory::NonTerminalMap NonTermMap;
|
2012-07-18 17:52:48 +04:00
|
|
|
|
2012-07-19 21:59:50 +04:00
|
|
|
/*
|
2013-05-24 19:33:30 +04:00
|
|
|
const PhraseDictionaryNodeMemory &coll = phraseDict.m_collection;
|
2012-07-18 17:52:48 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|