~ubuntu-branches/ubuntu/raring/sunpinyin/raring

« back to all changes in this revision

Viewing changes to src/ime-core/ic_history.cpp

  • Committer: Package Import Robot
  • Author(s): YunQiang Su
  • Date: 2012-03-30 15:31:55 UTC
  • mfrom: (1.1.3) (1.2.7 sid)
  • Revision ID: package-import@ubuntu.com-20120330153155-qgls77sogzgtg9zp
Tags: 2.0.3+git20120222-1
* Team upload: git snapshot 20120222.
   - fix breaks if LDFLAGS in environment contains
       multiple words (Closese #646001).
   - rm patches merged to upstream:
       append-os-environ-toenv.patch
       fix-ftbfs-on-sh.patch
       remove-10-candidate-words-limitation.patch
   - refresh disable-lm-dict-compile.patch.
* Bump stardard version to 3.9.3: no modify needed.
* add libsunpinyin3-dbg and python-sunpinyin packages.
* debian/compat to 9, multiarch it.
* rewrite debian/rules with dh 7 format.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 
 * 
 
3
 *
4
4
 * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
5
 
 * 
 
5
 *
6
6
 * The contents of this file are subject to the terms of either the GNU Lesser
7
7
 * General Public License Version 2.1 only ("LGPL") or the Common Development and
8
8
 * Distribution License ("CDDL")(collectively, the "License"). You may not use this
9
9
 * file except in compliance with the License. You can obtain a copy of the CDDL at
10
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 
 
11
 * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
12
12
 * specific language governing permissions and limitations under the License. When
13
13
 * distributing the software, include this License Header Notice in each file and
14
14
 * include the full text of the License in the License file as well as the
15
15
 * following notice:
16
 
 * 
 
16
 *
17
17
 * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
18
18
 * (CDDL)
19
19
 * For Covered Software in this distribution, this License shall be governed by the
21
21
 * Any litigation relating to this License shall be subject to the jurisdiction of
22
22
 * the Federal Courts of the Northern District of California and the state courts
23
23
 * of the State of California, with venue lying in Santa Clara County, California.
24
 
 * 
 
24
 *
25
25
 * Contributor(s):
26
 
 * 
 
26
 *
27
27
 * If you wish your version of this file to be governed by only the CDDL or only
28
28
 * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
29
29
 * include this software in this distribution under the [CDDL or LGPL Version 2.1]
32
32
 * Version 2.1, or to extend the choice of license to its licensees as provided
33
33
 * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
34
34
 * Version 2 license, then the option applies only if the new code is made subject
35
 
 * to such option by the copyright holder. 
 
35
 * to such option by the copyright holder.
36
36
 */
37
37
 
38
38
#ifdef HAVE_CONFIG_H
43
43
#include <stdio.h>
44
44
#include <stdint.h>
45
45
#include <cassert>
 
46
#include <arpa/inet.h>
46
47
#include <sys/stat.h>
47
48
#include <sys/types.h>
48
49
#include <algorithm>
49
50
#include "ic_history.h"
50
51
 
51
 
const unsigned CICHistory::DCWID = (unsigned)-1;
 
52
const uint32_t CICHistory::DCWID = (uint32_t)-1;
52
53
 
53
54
CICHistory::~CICHistory()
54
55
{
55
56
}
56
57
 
57
 
static bool bBigramHistoryInited = false;
58
 
const size_t  CBigramHistory::contxt_memory_size = 8192;
59
 
const double  CBigramHistory::focus_memory_ratio = 0.05;
 
58
const size_t CBigramHistory::contxt_memory_size = 8192;
 
59
const double CBigramHistory::focus_memory_ratio = 0.05;
60
60
 
61
61
//FIXME: CBigramHistory need to be thread safe
62
62
CBigramHistory::CBigramHistory() : m_memory(), m_unifreq(), m_bifreq()
68
68
{
69
69
}
70
70
 
71
 
bool CBigramHistory::memorize(unsigned* its_wid, unsigned* ite_wid)
 
71
bool
 
72
CBigramHistory::memorize(uint32_t* its_wid, uint32_t* ite_wid)
72
73
{
73
74
    TBigram bigram(DCWID, DCWID);
74
75
 
105
106
    return true;
106
107
}
107
108
 
108
 
void CBigramHistory::clear()
 
109
void
 
110
CBigramHistory::clear()
109
111
{
110
112
    m_memory.clear();
111
113
    m_unifreq.clear();
112
114
    m_bifreq.clear();
113
115
}
114
116
 
115
 
double CBigramHistory::pr(unsigned* its_wid, unsigned* ite_wid)
 
117
double
 
118
CBigramHistory::pr(uint32_t* its_wid, uint32_t* ite_wid)
116
119
{
117
120
    TBigram bigram(DCWID, DCWID);
118
121
    if (its_wid != ite_wid) {
119
122
        --ite_wid;
120
123
        bigram.second = *ite_wid;
121
124
        if (its_wid != ite_wid)
122
 
            bigram.first = *(ite_wid-1);
 
125
            bigram.first = *(ite_wid - 1);
123
126
    }
124
127
    return pr(bigram);
125
128
}
126
129
 
127
 
double CBigramHistory::pr(unsigned* its_wid, unsigned* ite_wid, unsigned wid)
 
130
double
 
131
CBigramHistory::pr(uint32_t* its_wid, uint32_t* ite_wid, uint32_t wid)
128
132
{
129
133
    TBigram bigram(DCWID, DCWID);
130
134
    if (its_wid != ite_wid)
131
 
        bigram.first = *(ite_wid-1);
 
135
        bigram.first = *(ite_wid - 1);
132
136
    bigram.second = wid;
133
137
    return pr(bigram);
134
138
}
135
139
 
136
 
inline uint16_t swap16(uint16_t x)
137
 
{
138
 
    return ((x << 8) | ((x >> 8) & 0xff));
139
 
}
140
 
 
141
 
inline uint32_t swap32(uint32_t x)
142
 
{
143
 
    return ((swap16(x) << 16) | (swap16(x >> 16) & 0xffff));
144
 
}
145
 
 
146
 
bool CBigramHistory::bufferize(void** buf_ptr, size_t* sz)
 
140
// htonl could be a macro, so wrap it in a func.
 
141
inline uint32_t
 
142
swap32(uint32_t x)
 
143
{
 
144
    return htonl(x);
 
145
}
 
146
 
 
147
bool
 
148
CBigramHistory::bufferize(void** buf_ptr, size_t* sz)
147
149
{
148
150
    *buf_ptr = NULL;
149
151
    *sz = 0;
154
156
#ifdef WORDS_BIGENDIAN
155
157
            std::copy(m_memory.begin(), m_memory.end(), (uint32_t*)*buf_ptr);
156
158
#else
157
 
            std::transform(m_memory.begin(), m_memory.end(), (uint32_t*)*buf_ptr, swap32);
 
159
            std::transform(m_memory.begin(),
 
160
                           m_memory.end(), (uint32_t*)*buf_ptr, swap32);
158
161
#endif
159
162
        }
160
163
        return true;
167
170
    return false;
168
171
}
169
172
 
170
 
bool CBigramHistory::loadFromFile (const char *fname)
 
173
bool
 
174
CBigramHistory::loadFromFile(const char *fname)
171
175
{
172
176
    m_history_path = fname;
173
177
 
174
178
    bool suc = false;
175
 
    int fd = open (fname, O_CREAT, 0600);
 
179
    int fd = open(fname, O_CREAT, 0600);
176
180
    if (fd == -1) {
177
 
        perror("fopen bi-gram");
 
181
        suc = loadFromBuffer(NULL, 0);
178
182
        return suc;
179
183
    }
180
 
    
 
184
 
181
185
    struct stat info;
182
 
    fstat (fd, &info);
183
 
    void* buf = malloc (info.st_size);
184
 
    
 
186
    fstat(fd, &info);
 
187
    void* buf = malloc(info.st_size);
 
188
 
185
189
    if (buf) {
186
 
        read (fd, buf, info.st_size);
187
 
        suc = loadFromBuffer (buf, info.st_size);
188
 
        free (buf);
189
 
    }  
190
 
    close (fd);
 
190
        read(fd, buf, info.st_size);
 
191
        suc = loadFromBuffer(buf, info.st_size);
 
192
        free(buf);
 
193
    }
 
194
    close(fd);
191
195
    return suc;
192
196
}
193
197
 
194
 
bool CBigramHistory::saveToFile(const char *fname)
 
198
bool
 
199
CBigramHistory::saveToFile(const char *fname)
195
200
{
196
201
    if (!fname)
197
202
        fname = m_history_path.c_str();
200
205
    size_t sz = 0;
201
206
    void* buf = NULL;
202
207
    if (bufferize(&buf, &sz) && buf) {
203
 
        FILE* fp = fopen (fname, "wb");
 
208
        FILE* fp = fopen(fname, "wb");
204
209
        if (fp) {
205
210
            suc = (fwrite(buf, 1, sz, fp) == sz);
206
211
            fclose(fp);
210
215
    return suc;
211
216
}
212
217
 
213
 
bool CBigramHistory::loadFromBuffer(void* buf_ptr, size_t sz)
 
218
bool
 
219
CBigramHistory::loadFromBuffer(void* buf_ptr, size_t sz)
214
220
{
215
221
    clear();
216
222
 
217
223
    sz /= sizeof(uint32_t);
218
 
    uint32_t *pw = (uint32_t *)buf_ptr;
 
224
    uint32_t *pw = (uint32_t*)buf_ptr;
219
225
 
220
226
    if (pw && sz > 0) {
221
227
#ifndef WORDS_BIGENDIAN
222
 
        std::transform(pw, pw+sz, pw, swap32);
 
228
        std::transform(pw, pw + sz, pw, swap32);
223
229
#endif
224
230
        TBigram bigram(DCWID, DCWID);
225
 
        for (unsigned i=0; i < sz; ++i) {
 
231
        for (size_t i = 0; i < sz; ++i) {
226
232
            bigram.first = bigram.second;
227
233
            bigram.second = *pw++;
228
234
            m_memory.push_back(bigram.second);
233
239
    return true;
234
240
}
235
241
 
236
 
double CBigramHistory::pr(TBigram& bigram)
 
242
double
 
243
CBigramHistory::pr(TBigram& bigram)
237
244
{
238
245
    int uf0 = uniFreq(bigram.first);
239
246
    int bf = biFreq(bigram);
240
247
    int uf1 = uniFreq(bigram.second);
241
248
 
242
249
    double pr = 0.0;
243
 
    pr += 0.68*double(bf)/double(uf0+0.5);
244
 
    pr += 0.32*double(uf1)/double(m_memory.size() + (contxt_memory_size-m_memory.size())/10);
 
250
    pr += 0.68 * double(bf) / double(uf0 + 0.5);
 
251
    pr += 0.32 * double(uf1) /
 
252
          double(m_memory.size() + (contxt_memory_size - m_memory.size()) / 10);
245
253
 
246
254
#ifdef DEBUG
247
255
    if (pr != 0)
252
260
    return pr;
253
261
}
254
262
 
255
 
int  CBigramHistory::uniFreq(TUnigram& ug)
 
263
int
 
264
CBigramHistory::uniFreq(TUnigram& ug)
256
265
{
257
266
    int freq = 0;
258
267
    if (m_stopWords.find(ug) == m_stopWords.end()) {
260
269
        if (it != m_unifreq.end()) {
261
270
            freq = it->second;
262
271
            TContextMemory::reverse_iterator rit = m_memory.rbegin();
263
 
            for (int i = 0; rit != m_memory.rend() && i < contxt_memory_size * focus_memory_ratio; i++) {
 
272
            for (int i =
 
273
                     0;
 
274
                 rit != m_memory.rend() && i < contxt_memory_size *
 
275
                 focus_memory_ratio;
 
276
                 i++) {
264
277
                if (*rit == ug)
265
278
                    freq += 1.0 / focus_memory_ratio;
266
279
                *rit++;
271
284
    return freq / 2;
272
285
}
273
286
 
274
 
int  CBigramHistory::biFreq(TBigram& bg)
 
287
int
 
288
CBigramHistory::biFreq(TBigram& bg)
275
289
{
276
290
    int freq = 0;
277
291
    //std::set<unsigned>::const_iterator ite = m_stopWords.end();
278
 
    if (m_stopWords.find(bg.first) != m_stopWords.end()
279
 
        && m_stopWords.find(bg.second) != m_stopWords.end()) {
 
292
    if (m_stopWords.find(bg.first) == m_stopWords.end()
 
293
        && m_stopWords.find(bg.second) == m_stopWords.end()) {
280
294
        TBigramPool::const_iterator it = m_bifreq.find(bg);
281
295
        if (it != m_bifreq.end()) {
282
 
            freq =  it->second;
 
296
            freq = it->second;
283
297
            TContextMemory::reverse_iterator re = m_memory.rbegin();
284
298
            TContextMemory::reverse_iterator rs = re + 1;
285
 
            for (int i = 0; rs != m_memory.rend() && i < contxt_memory_size * focus_memory_ratio; i++) {
 
299
            for (int i = 0;
 
300
                 rs != m_memory.rend() && i < contxt_memory_size *
 
301
                 focus_memory_ratio;
 
302
                 i++) {
286
303
                if (*rs == bg.first && *re == bg.second)
287
304
                    freq += 1.0 / focus_memory_ratio;
288
305
                ++rs; ++re;
294
311
    return freq;
295
312
}
296
313
 
297
 
void CBigramHistory::decUniFreq(TUnigram& ug)
 
314
void
 
315
CBigramHistory::decUniFreq(TUnigram& ug)
298
316
{
299
317
    TUnigramPool::iterator it = m_unifreq.find(ug);
300
318
    if (it != m_unifreq.end()) {
305
323
    }
306
324
}
307
325
 
308
 
bool CBigramHistory::seenBefore(unsigned wid)
 
326
bool
 
327
CBigramHistory::seenBefore(uint32_t wid)
309
328
{
310
 
    return (wid != DCWID && m_stopWords.find(wid) == m_stopWords.end() &&
311
 
            m_unifreq.find(wid) != m_unifreq.end());
 
329
    return(wid != DCWID && m_stopWords.find(wid) == m_stopWords.end() &&
 
330
           m_unifreq.find(wid) != m_unifreq.end());
312
331
}
313
332
 
314
 
void CBigramHistory::decBiFreq(TBigram& bg)
 
333
void
 
334
CBigramHistory::decBiFreq(TBigram& bg)
315
335
{
316
336
    TBigramPool::iterator it = m_bifreq.find(bg);
317
337
    if (it != m_bifreq.end()) {
322
342
    }
323
343
}
324
344
 
325
 
void CBigramHistory::incUniFreq(TUnigram& ug)
 
345
void
 
346
CBigramHistory::incUniFreq(TUnigram& ug)
326
347
{
327
348
    ++m_unifreq[ug];
328
349
    //printf("Remebering uniFreq[%d]-->%d\n", ug, m_unifreq[ug]);
329
350
}
330
351
 
331
 
void CBigramHistory::incBiFreq(TBigram& bg)
 
352
void
 
353
CBigramHistory::incBiFreq(TBigram& bg)
332
354
{
333
355
    ++m_bifreq[bg];
334
356
    //printf("Remebering biFreq[%d,%d]-->%d\n", bg.first, bg.second, m_bifreq[bg]);
338
360
// a better data structure for this.
339
361
//
340
362
// And Even though, we may also need to remove the individual characters in this
341
 
// word (identified by wid), which is current infeasible, 
 
363
// word (identified by wid), which is current infeasible,
342
364
//
343
365
// Here are what we need to do:
344
366
//   1. get the wstring by word id from userdict
346
368
//   3. get the word id from each character from system lexicon (not supported yet)
347
369
//   4. remove the unigrams and bigrams of each character, and the entire word
348
370
//
349
 
void CBigramHistory::forget(unsigned wid)
 
371
void
 
372
CBigramHistory::forget(uint32_t wid)
350
373
{
351
 
    TUnigramPool::iterator uni_it = m_unifreq.find (wid);
 
374
    TUnigramPool::iterator uni_it = m_unifreq.find(wid);
352
375
    if (uni_it != m_unifreq.end())
353
376
        m_unifreq.erase(uni_it);
354
377
 
355
 
    TBigramPool::iterator it  = m_bifreq.begin();
 
378
    TBigramPool::iterator it = m_bifreq.begin();
356
379
    TBigramPool::iterator ite = m_bifreq.end();
357
380
 
358
381
    while (it != ite) {
359
382
        TBigram bigram = it->first;
360
 
        
 
383
 
361
384
        if (bigram.first == wid || bigram.second == wid)
362
 
            m_bifreq.erase (it++);
 
385
            m_bifreq.erase(it++);
363
386
        else
364
387
            ++it;
365
388
    }
366
389
}
367
390
 
368
 
void CBigramHistory::forget(unsigned *its_wid, unsigned *ite_wid)
 
391
void
 
392
CBigramHistory::forget(uint32_t *its_wid, uint32_t *ite_wid)
369
393
{
370
394
    for (; its_wid < ite_wid; ++its_wid) {
371
395
        TBigram bigram(*its_wid, DCWID);
372
396
 
373
 
        if (its_wid+1 != ite_wid)
374
 
            bigram.second = *(its_wid+1);
 
397
        if (its_wid + 1 != ite_wid)
 
398
            bigram.second = *(its_wid + 1);
375
399
 
376
400
        TBigramPool::iterator it = m_bifreq.find(bigram);
377
401
        if (it != m_bifreq.end())
379
403
    }
380
404
}
381
405
 
382
 
void CBigramHistory::addStopWords(const std::set<unsigned int>& stopWords)
 
406
void
 
407
CBigramHistory::addStopWords(const std::set<uint32_t>& stopWords)
383
408
{
384
 
    m_stopWords.insert (stopWords.begin(), stopWords.end());
 
409
    m_stopWords.insert(stopWords.begin(), stopWords.end());
385
410
}
386
411
 
387
 
void CBigramHistory::initStopWords()
 
412
void
 
413
CBigramHistory::initStopWords()
388
414
{
389
415
    m_stopWords.clear();
390
 
    
 
416
 
391
417
    m_stopWords.insert(0);     //unknown world
392
418
    m_stopWords.insert(DCWID); //seperator word id used by history memory interanlly
393
419
}