Tizen 2.1 base
[platform/core/uifw/ise-engine-sunpinyin.git] / src / slm / tslminfo / tslminfo.cpp
1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3  *
4  * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
5  *
6  * The contents of this file are subject to the terms of either the GNU Lesser
7  * General Public License Version 2.1 only ("LGPL") or the Common Development and
8  * Distribution License ("CDDL")(collectively, the "License"). You may not use this
9  * file except in compliance with the License. You can obtain a copy of the CDDL at
10  * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
11  * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
12  * specific language governing permissions and limitations under the License. When
13  * distributing the software, include this License Header Notice in each file and
14  * include the full text of the License in the License file as well as the
15  * following notice:
16  *
17  * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
18  * (CDDL)
19  * For Covered Software in this distribution, this License shall be governed by the
20  * laws of the State of California (excluding conflict-of-law provisions).
21  * Any litigation relating to this License shall be subject to the jurisdiction of
22  * the Federal Courts of the Northern District of California and the state courts
23  * of the State of California, with venue lying in Santa Clara County, California.
24  *
25  * Contributor(s):
26  *
27  * If you wish your version of this file to be governed by only the CDDL or only
28  * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
29  * include this software in this distribution under the [CDDL or LGPL Version 2.1]
30  * license." If you don't indicate a single choice of license, a recipient has the
31  * option to distribute your version of this file under either the CDDL or the LGPL
32  * Version 2.1, or to extend the choice of license to its licensees as provided
33  * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
34  * Version 2 license, then the option applies only if the new code is made subject
35  * to such option by the copyright holder.
36  */
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #ifdef HAVE_ASSERT_H
43 #include <assert.h>
44 #endif
45
46 #ifdef HAVE_GETOPT_H
47 #include <getopt.h>
48 #endif
49
50 #include <stdio.h>
51 #include <string>
52 #include <math.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55
56 #include <vector>
57 #include <map>
58
59 #include "../slm.h"
60
61 class CIterateThreadSlm : public CThreadSlm {
62 public:
63     typedef std::vector<TState> iterator;
64
65     int
66     getLevelSize(int lvl)
67     {
68         return m_LevelSizes[lvl];
69     }
70
71     int
72     getN()
73     {
74         return m_N;
75     }
76
77     bool
78     beginLevel(int lvl, iterator& it);
79
80     void
81     next(iterator& it)
82     {
83         ++(it.back()); adjustIterator(it);
84     }
85
86     bool
87     isEnd(iterator& it)
88     {
89         return (int) ((it.back().getIdx()) + 1)
90             == getLevelSize(it.back().getLevel());
91     }
92
93     void*
94     getNodePtr(TState s);
95
96     double
97     mapPr(unsigned int pr_idx, bool log_format) const
98     {
99         double val = m_prTable[pr_idx];
100         if (log_format) {
101             return (m_UseLogPr) ? (val) : (-log(val));
102         } else {
103             return (m_UseLogPr) ? (exp(-val)) : (val);
104         }
105     }
106
107     double
108     mapBow(unsigned int bow_idx, bool log_format) const
109     {
110         double val = m_bowTable[bow_idx];
111         if (log_format) {
112             return (m_UseLogPr) ? (val) : (-log(val));
113         } else {
114             return (m_UseLogPr) ? (exp(-val)) : (val);
115         }
116     }
117
118 protected:
119     void
120     adjustIterator(iterator& it);
121 };
122
123 bool
124 CIterateThreadSlm::beginLevel(int lvl, iterator& it)
125 {
126     it.clear();
127     if (lvl > (int) m_N) return false;
128     for (int i = 0; i <= lvl; ++i)
129         it.push_back(TState(i, 0));
130     adjustIterator(it);
131     return true;
132 }
133
134 void*
135 CIterateThreadSlm::getNodePtr(TState s)
136 {
137     unsigned int lvl = s.getLevel();
138     if (lvl == m_N) {
139         return(((TLeaf*)m_Levels[lvl]) + s.getIdx());
140     } else {
141         return(((TNode*)m_Levels[lvl]) + s.getIdx());
142     }
143 }
144
145 void
146 CIterateThreadSlm::adjustIterator(iterator& it)
147 {
148 //    if (!isEnd(it)) {
149     for (int lvl = it.size() - 2; lvl >= 0; --lvl) {
150         int sz = getLevelSize(lvl);
151         unsigned child = (it[lvl + 1]).getIdx();
152         while ((int) it[lvl].getIdx() < (sz - 1) &&
153                (((TNode*)getNodePtr(it[lvl])) + 1)->ch() <= child) {
154             ++(it[lvl]);
155         }
156     }
157 //    }
158 }
159
160 void
161 ShowUsage()
162 {
163     printf("Usage:\n");
164     printf("    tslminfo [options] threaded_slm_file\n");
165     printf("\nDescription:\n");
166     printf(
167         "    tslminfo tell information of a threaded back-off language model 'threaded_slm_file'. It can also print the model to ARPA format.");
168     printf(
169         " When no options given, slminfo will only print number of items in each level of the language model.\n");
170     printf("\nOptions:\n");
171     printf("    -v             # Verbose mode, printing arpa format.\n");
172     printf(
173         "    -p             # Prefer normal probability instead of -log(Pr) which is default. Valid under -v option.\n");
174     printf(
175         "    -l dict_file   # Lexicon. Valid under -v option. Substitute the word-id with word-text in the output.\n");
176     printf("\n");
177     exit(100);
178 }
179
180 static bool verbose = false;
181 static char *lexicon_filename = NULL;
182 static bool use_log_pr = true;
183
184 static struct option long_options[] =
185 {
186     { "verbose", 0, 0, 'v' },
187     { "pr", 0, 0, 'p' },
188     { "lexicon", 1, 0, 'l' },
189     { 0, 0, 0, 0 }
190 };
191
192 static void
193 getParameters(int argc, char* argv[])
194 {
195     int c, option_index = 0;
196     while ((c =
197                 getopt_long(argc, argv, "vpl:", long_options,
198                             &option_index)) != -1) {
199         switch (c) {
200         case 'v':
201             verbose = true;
202             break;
203         case 'l':
204             lexicon_filename = strdup(optarg);
205             break;
206         case 'p':
207             use_log_pr = false;
208             break;
209         default:
210             ShowUsage();
211         }
212     }
213     if (use_log_pr == false && !verbose) ShowUsage();
214     if (lexicon_filename != NULL && !verbose) ShowUsage();
215     if (optind != argc - 1) ShowUsage();
216 }
217
218 typedef std::map<unsigned int, std::string> TReverseLexicon;
219
220
221 void
222 PrintARPA(CIterateThreadSlm& itslm,
223           const char* lexicon_filename,
224           bool use_log_pr)
225 {
226     static unsigned int id;
227     static char word[10240];
228
229     TReverseLexicon* plexicon = NULL;
230     if (lexicon_filename != NULL) {
231         plexicon = new TReverseLexicon();
232         FILE* f_lex = fopen(lexicon_filename, "r");
233         while (fgets(word, 10240, f_lex) != NULL) {
234             if (strlen(word) > 0) {
235                 char* p = word;
236                 while (*p == ' ' || *p == '\t')
237                     ++p;
238                 while (*p != 0 && *p != ' ' && *p != '\t')
239                     ++p;
240                 if (*p == 0) continue;
241                 *p++ = 0;
242                 while (*p == ' ' || *p == '\t')
243                     ++p;
244                 if (!(*p >= '0' && *p <= '9')) continue;
245                 for (id = 0; *p >= '0' && *p <= '9'; ++p)
246                     id = 10 * id + (*p - '0');
247                 (*plexicon)[id] = std::string(word);
248             }
249         }
250         fclose(f_lex);
251     }
252
253     CIterateThreadSlm::iterator it;
254     for (int lvl = 0; lvl <= itslm.getN(); ++lvl) {
255         printf("\\%d-gram\\%d\n", lvl, itslm.getLevelSize(lvl) - 1);
256         for (itslm.beginLevel(lvl, it); !itslm.isEnd(it); itslm.next(it)) {
257             for (int i = 1; i < lvl; ++i) {
258                 CIterateThreadSlm::TNode*pn =
259                     (CIterateThreadSlm::TNode*)itslm.getNodePtr(it[i]);
260                 if (plexicon != NULL)
261                     printf("%s ", (*plexicon)[pn->wid()].c_str());
262                 else
263                     printf("%9d ", pn->wid());
264             }
265             if (lvl < itslm.getN()) {
266                 CIterateThreadSlm::TNode*pn =
267                     (CIterateThreadSlm::TNode*)itslm.getNodePtr(it[lvl]);
268                 if (lvl > 0) {
269                     if (plexicon != NULL)
270                         printf("%s ", ((*plexicon)[pn->wid()]).c_str());
271                     else
272                         printf("%9d ", pn->wid());
273                 }
274
275                 double pr = itslm.mapPr(pn->pr(), use_log_pr);
276                 double bow = itslm.mapBow(pn->bow(), use_log_pr);
277                 printf("%16.12lf %16.12lf ", pr, bow);
278                 printf("(%1u,%u)\n", pn->bol(), pn->bon());
279             } else {
280                 CIterateThreadSlm::TLeaf*pn =
281                     (CIterateThreadSlm::TLeaf*)itslm.getNodePtr(it[lvl]);
282                 if (lvl > 0) {
283                     if (plexicon != NULL)
284                         printf("%s ", ((*plexicon)[pn->wid()]).c_str());
285                     else
286                         printf("%9d ", pn->wid());
287                 }
288
289                 double pr = itslm.mapPr(pn->pr(), use_log_pr);
290                 printf("%16.12lf ", pr);
291                 printf("(%1u,%u)\n", pn->bol(), pn->bon());
292             }
293         }
294     }
295
296     delete plexicon;
297 }
298
299
300 /**
301  * tslminfo [-v] threaded_slm_file
302  */
303 int
304 main(int argc, char* argv[])
305 {
306     getParameters(argc, argv);
307
308     CIterateThreadSlm itslm;
309
310     if (itslm.load(argv[argc - 1], true)) {
311         if (!verbose) {
312             printf("Total %d level ngram: ", itslm.getN());
313             for (int lvl = 1; lvl <= itslm.getN(); ++lvl)
314                 printf("%d ", itslm.getLevelSize(lvl) - 1);
315             printf(
316                 (itslm.isUseLogPr()) ? " using -log(pr)\n" :
317                 " using direct pr\n");
318         } else {
319             PrintARPA(itslm, lexicon_filename, use_log_pr);
320         }
321         itslm.free();
322         return 0;
323     }
324     return 100;
325 }