OSDN Git Service

設定変更。
[wordring-tm/wordring-tm.git] / third_party / mecab-0.996 / src / eval.cpp
1 //  MeCab -- Yet Another Part-of-Speech and Morphological Analyzer
2 //
3 //
4 //  Copyright(C) 2001-2006 Taku Kudo <taku@chasen.org>
5 //  Copyright(C) 2004-2006 Nippon Telegraph and Telephone Corporation
6 #include <cstdio>
7 #include <fstream>
8 #include <iostream>
9 #include <map>
10 #include <vector>
11 #include "common.h"
12 #include "mecab.h"
13 #include "param.h"
14 #include "stream_wrapper.h"
15 #include "scoped_ptr.h"
16 #include "utils.h"
17
18 namespace MeCab {
19
20 class Eval {
21  private:
22   static bool read(std::istream *is,
23                    std::vector<std::vector<std::string> > *r,
24                    const std::vector<int> &level) {
25     if (!*is) {
26       return false;
27     }
28
29     char *col[2];
30     scoped_fixed_array<char, BUF_SIZE> buf;
31     scoped_fixed_array<char *, BUF_SIZE> csv;
32     r->clear();
33     while (is->getline(buf.get(), buf.size())) {
34       if (std::strcmp(buf.get(), "EOS") == 0) {
35         break;
36       }
37       CHECK_DIE(tokenize(buf.get(), "\t", col,  2) == 2) << "format error";
38       csv[0] = col[0];
39       size_t n = tokenizeCSV(col[1], csv.get() + 1, csv.size() - 1);
40       std::vector<std::string> tmp;
41       for (size_t i = 0; i < level.size(); ++i) {
42         size_t m = level[i] < 0 ? n : level[i];
43         CHECK_DIE(m <= n) << " out of range " << level[i];
44         std::string output;
45         for (size_t j = 0; j <= m; ++j) {
46           output += csv[j];
47           if (j != 0) {
48             output += "\t";
49           }
50         }
51         tmp.push_back(output);
52       }
53       r->push_back(tmp);
54     }
55
56     return true;
57   }
58
59   static bool parseLevel(const char *level_str,
60                          std::vector<int> *level) {
61     scoped_fixed_array<char, BUF_SIZE> buf;
62     scoped_fixed_array<char *, 512> col;
63     std::strncpy(buf.get(), level_str, buf.size());
64     level->clear();
65     size_t n = tokenize2(buf.get(), "\t ", col.get(), col.size());
66     for (size_t i = 0; i < n; ++i) {
67       level->push_back(std::atoi(col[i]));
68     }
69     return true;
70   }
71
72   static void printeval(std::ostream *os, size_t c, size_t p, size_t r) {
73     double pr = (p == 0) ? 0 : 100.0 * c/p;
74     double re = (r == 0) ? 0 : 100.0 * c/r;
75     double F = ((pr + re) == 0.0) ? 0 : 2 * pr * re /(pr + re);
76     scoped_fixed_array<char, BUF_SIZE> buf;
77     sprintf(buf.get(), "%4.4f(%d/%d) %4.4f(%d/%d) %4.4f\n",
78             pr,
79             static_cast<int>(c),
80             static_cast<int>(p),
81             re,
82             static_cast<int>(c),
83             static_cast<int>(r),
84             F);
85     *os << buf.get();
86   }
87
88  public:
89   static bool eval(int argc, char **argv) {
90     static const MeCab::Option long_options[] = {
91       { "level",  'l',  "0 -1",    "STR",    "set level of evaluations" },
92       { "output", 'o',  0,         "FILE",   "set the output file name" },
93       { "version",  'v',  0,   0,    "show the version and exit"   },
94       { "help",  'h',  0,   0,    "show this help and exit."   },
95       { 0, 0, 0, 0 }
96     };
97
98     MeCab::Param param;
99     param.open(argc, argv, long_options);
100
101     if (!param.open(argc, argv, long_options)) {
102       std::cout << param.what() << "\n\n" <<  COPYRIGHT
103                 << "\ntry '--help' for more information." << std::endl;
104       return -1;
105     }
106
107     if (!param.help_version()) return 0;
108
109     const std::vector<std::string> &files = param.rest_args();
110     if (files.size() < 2) {
111       std::cout << "Usage: " <<
112           param.program_name() << " output answer" << std::endl;
113       return -1;
114     }
115
116     std::string output = param.get<std::string>("output");
117     if (output.empty()) output = "-";
118     MeCab::ostream_wrapper ofs(output.c_str());
119     CHECK_DIE(*ofs) << "no such file or directory: " << output;
120
121     const std::string system = files[0];
122     const std::string answer = files[1];
123
124     const std::string level_str = param.get<std::string>("level");
125
126     std::ifstream ifs1(WPATH(files[0].c_str()));
127     std::ifstream ifs2(WPATH(files[1].c_str()));
128
129     CHECK_DIE(ifs1) << "no such file or directory: " << files[0].c_str();
130     CHECK_DIE(ifs2) << "no such file or directory: " << files[0].c_str();
131     CHECK_DIE(!level_str.empty()) << "level_str is NULL";
132
133     std::vector<int> level;
134     parseLevel(level_str.c_str(), &level);
135     CHECK_DIE(level.size()) << "level_str is empty: " << level_str;
136     std::vector<size_t> result_tbl(level.size());
137     std::fill(result_tbl.begin(), result_tbl.end(), 0);
138
139     size_t prec = 0;
140     size_t recall = 0;
141
142     std::vector<std::vector<std::string> > r1;
143     std::vector<std::vector<std::string> > r2;
144
145     while (true) {
146       if (!read(&ifs1, &r1, level) || !read(&ifs2, &r2, level))
147         break;
148
149       size_t i1 = 0;
150       size_t i2 = 0;
151       size_t p1 = 0;
152       size_t p2 = 0;
153
154       while (i1 < r1.size() && i2 < r2.size()) {
155         if (p1 == p2) {
156           for (size_t i = 0; i < result_tbl.size(); ++i) {
157             if (r1[i1][i] == r2[i2][i]) {
158               result_tbl[i]++;
159             }
160           }
161           p1 += r1[i1][0].size();
162           p2 += r2[i2][0].size();
163           ++i1;
164           ++i2;
165           ++prec;
166           ++recall;
167         } else if (p1 < p2) {
168           p1 += r1[i1][0].size();
169           ++i1;
170           ++prec;
171         } else {
172           p2 += r2[i2][0].size();
173           ++i2;
174           ++recall;
175         }
176       }
177
178       while (i1 < r1.size()) {
179         ++prec;
180         ++i1;
181       }
182
183       while (i2 < r2.size()) {
184         ++recall;
185         ++i2;
186       }
187     }
188
189     *ofs <<  "              precision          recall         F"
190          << std::endl;
191     for (size_t i = 0; i < result_tbl.size(); ++i) {
192       if (level[i] == -1) {
193         *ofs << "LEVEL ALL: ";
194       } else {
195         *ofs << "LEVEL " << level[i] << ":    ";
196       }
197       printeval(&*ofs, result_tbl[i], prec, recall);
198     }
199
200     return true;
201   }
202 };
203
204 class TestSentenceGenerator {
205  public:
206   static int run(int argc, char **argv) {
207     static const MeCab::Option long_options[] = {
208       { "output",   'o',  0,   "FILE", "set the output filename" },
209       { "version",  'v',  0,   0,    "show the version and exit"   },
210       { "help",  'h',  0,   0,    "show this help and exit."   },
211       { 0, 0, 0, 0 }
212     };
213
214     MeCab::Param param;
215     param.open(argc, argv, long_options);
216
217     if (!param.open(argc, argv, long_options)) {
218       std::cout << param.what() << "\n\n" <<  COPYRIGHT
219                 << "\ntry '--help' for more information." << std::endl;
220       return -1;
221     }
222
223     if (!param.help_version()) {
224       return 0;
225     }
226
227     const std::vector<std::string> &tmp = param.rest_args();
228     std::vector<std::string> files = tmp;
229     if (files.empty()) {
230       files.push_back("-");
231     }
232
233     std::string output = param.get<std::string>("output");
234     if (output.empty()) output = "-";
235     MeCab::ostream_wrapper ofs(output.c_str());
236     CHECK_DIE(*ofs) << "permission denied: " << output;
237
238     scoped_fixed_array<char, BUF_SIZE> buf;
239     char *col[2];
240     std::string str;
241     for (size_t i = 0; i < files.size(); ++i) {
242       MeCab::istream_wrapper ifs(files[i].c_str());
243       CHECK_DIE(*ifs) << "no such file or directory: " << files[i];
244       while (ifs->getline(buf.get(), buf.size())) {
245         const size_t n = tokenize(buf.get(), "\t ", col, 2);
246         CHECK_DIE(n <= 2) << "format error: " << buf.get();
247         if (std::strcmp(col[0], "EOS") == 0 && !str.empty()) {
248           *ofs << str << std::endl;
249           str.clear();
250         } else {
251           str += col[0];
252         }
253       }
254     }
255
256     return 0;
257   }
258 };
259 }
260
261 // exports
262 int mecab_system_eval(int argc, char **argv) {
263   return MeCab::Eval::eval(argc, argv);
264 }
265
266 int mecab_test_gen(int argc, char **argv) {
267   return MeCab::TestSentenceGenerator::run(argc, argv);
268 }