00001 #include "MeteorScorer.h"
00002
00003 #include <algorithm>
00004 #include <cmath>
00005 #include <fstream>
00006 #include <iterator>
00007 #include <sstream>
00008 #include <stdexcept>
00009 #include <cstdio>
00010 #include <string>
00011 #include <vector>
00012
00013 #include <boost/thread/mutex.hpp>
00014
00015 #if defined(__GLIBCXX__) || defined(__GLIBCPP__)
00016 #include "Fdstream.h"
00017 #endif
00018
00019 #include "ScoreStats.h"
00020 #include "Util.h"
00021
00022 using namespace std;
00023
00024 namespace MosesTuning
00025 {
00026
00027
00028 #if (defined(__GLIBCXX__) || defined(__GLIBCPP__)) && !defined(_WIN32)
00029
00030
00031 #define CHILD_STDIN_READ pipefds_input[0]
00032 #define CHILD_STDIN_WRITE pipefds_input[1]
00033 #define CHILD_STDOUT_READ pipefds_output[0]
00034 #define CHILD_STDOUT_WRITE pipefds_output[1]
00035
00036 MeteorScorer::MeteorScorer(const string& config)
00037 : StatisticsBasedScorer("METEOR",config)
00038 {
00039 meteor_jar = getConfig("jar", "");
00040 meteor_lang = getConfig("lang", "en");
00041 meteor_task = getConfig("task", "tune");
00042 meteor_m = getConfig("m", "");
00043 meteor_p = getConfig("p", "");
00044 meteor_w = getConfig("w", "");
00045 if (meteor_jar == "") {
00046 throw runtime_error("Meteor jar required, see MeteorScorer.h for full list of options: --scconfig jar:/path/to/meteor-1.4.jar");
00047 }
00048 int pipe_status;
00049 int pipefds_input[2];
00050 int pipefds_output[2];
00051
00052 pipe_status = pipe(pipefds_input);
00053 if (pipe_status == -1) {
00054 throw runtime_error("Error creating pipe");
00055 }
00056 pipe_status = pipe(pipefds_output);
00057 if (pipe_status == -1) {
00058 throw runtime_error("Error creating pipe");
00059 }
00060
00061 pid_t pid;
00062 pid = fork();
00063 if (pid == pid_t(0)) {
00064
00065 dup2(CHILD_STDIN_READ, 0);
00066 dup2(CHILD_STDOUT_WRITE, 1);
00067 close(CHILD_STDIN_WRITE);
00068 close(CHILD_STDOUT_READ);
00069
00070 stringstream meteor_cmd;
00071 meteor_cmd << "java -Xmx1G -jar " << meteor_jar << " - - -stdio -lower -t " << meteor_task << " -l " << meteor_lang;
00072 if (meteor_m != "") {
00073 meteor_cmd << " -m '" << meteor_m << "'";
00074 }
00075 if (meteor_p != "") {
00076 meteor_cmd << " -p '" << meteor_p << "'";
00077 }
00078 if (meteor_w != "") {
00079 meteor_cmd << " -w '" << meteor_w << "'";
00080 }
00081 TRACE_ERR("Executing: " + meteor_cmd.str() + "\n");
00082 execl("/bin/bash", "bash", "-c", meteor_cmd.str().c_str(), (char*)NULL);
00083 throw runtime_error("Continued after execl");
00084 }
00085
00086 close(CHILD_STDIN_READ);
00087 close(CHILD_STDOUT_WRITE);
00088 m_to_meteor = new ofdstream(CHILD_STDIN_WRITE);
00089 m_from_meteor = new ifdstream(CHILD_STDOUT_READ);
00090 }
00091
00092 MeteorScorer::~MeteorScorer()
00093 {
00094
00095 delete m_to_meteor;
00096 delete m_from_meteor;
00097 }
00098
00099 void MeteorScorer::setReferenceFiles(const vector<string>& referenceFiles)
00100 {
00101
00102 for (int incRefs = 0; incRefs < (int)referenceFiles.size(); incRefs++) {
00103 m_references.clear();
00104 ifstream in(referenceFiles.at(incRefs).c_str());
00105 if (!in) {
00106 throw runtime_error("Unable to open " + referenceFiles.at(incRefs));
00107 }
00108 string line;
00109 while (getline(in, line)) {
00110 line = this->preprocessSentence(line);
00111 m_references.push_back(line);
00112 }
00113 m_multi_references.push_back(m_references);
00114 }
00115 m_references=m_multi_references.at(0);
00116 }
00117
00118 void MeteorScorer::prepareStats(size_t sid, const string& text, ScoreStats& entry)
00119 {
00120 string sentence = this->preprocessSentence(text);
00121 string stats_str;
00122 stringstream input;
00123
00124 input << "SCORE";
00125 for (int incRefs = 0; incRefs < (int)m_multi_references.size(); incRefs++) {
00126 if (sid >= m_multi_references.at(incRefs).size()) {
00127 stringstream msg;
00128 msg << "Sentence id (" << sid << ") not found in reference set";
00129 throw runtime_error(msg.str());
00130 }
00131 string ref = m_multi_references.at(incRefs).at(sid);
00132 input << " ||| " << ref;
00133 }
00134 input << " ||| " << text << "\n";
00135
00136 #ifdef WITH_THREADS
00137 mtx.lock();
00138 #endif
00139
00140 *m_to_meteor << input.str();
00141 m_from_meteor->getline(stats_str);
00142
00143 #ifdef WITH_THREADS
00144 mtx.unlock();
00145 #endif
00146 entry.set(stats_str);
00147 }
00148
00149 float MeteorScorer::calculateScore(const vector<ScoreStatsType>& comps) const
00150 {
00151 string score;
00152 stringstream input;
00153
00154 input << "EVAL |||";
00155 copy(comps.begin(), comps.end(), ostream_iterator<int>(input, " "));
00156 input << "\n";
00157
00158 #ifdef WITH_THREADS
00159 mtx.lock();
00160 #endif
00161
00162 *m_to_meteor << input.str();
00163 m_from_meteor->getline(score);
00164
00165 #ifdef WITH_THREADS
00166 mtx.unlock();
00167 #endif
00168 return atof(score.c_str());
00169 }
00170
00171 #else
00172
00173
00174
00175 MeteorScorer::MeteorScorer(const string& config)
00176 : StatisticsBasedScorer("METEOR",config)
00177 {
00178 throw runtime_error("Meteor unsupported, requires GLIBCXX");
00179 }
00180
00181 MeteorScorer::~MeteorScorer() {}
00182
00183 void MeteorScorer::setReferenceFiles(const vector<string>& referenceFiles) {}
00184
00185 void MeteorScorer::prepareStats(size_t sid, const string& text, ScoreStats& entry) {}
00186
00187 float MeteorScorer::calculateScore(const vector<ScoreStatsType>& comps) const
00188 {
00189
00190 return 0.0;
00191 }
00192
00193 #endif
00194
00195 }