(linenum→info "unix/slp.c:2238")

anthy/9100e/src-ordering/candswap.c

    1: /*
    2:  * 候補の交換のヒストリを管理する。
    3:  *
    4:  * anthy_swap_cand_ent() で学習する
    5:  * anthy_proc_swap_candidate() で学習結果を用いる
    6:  *
    7:  *  「田端が」という候補をトップに出して「田畑が」で確定された場合は
    8:  *  自立語部:「田端」->「田畑」
    9:  *    の二つのエントリを追加する
   10:  *
   11:  */
   12: #include <stdlib.h>
   13: 
   14: #include <anthy/record.h>
   15: #include <anthy/segment.h>
   16: /* for OCHAIRE_SCORE */
   17: #include <anthy/splitter.h>
   18: #include "sorter.h"
   19: 
   20: #define MAX_INDEP_PAIR_ENTRY 100
   21: 
   22: /* 候補の自立語部を学習する */
   23: static void
   24: learn_swap_cand_indep(struct cand_ent *o, struct cand_ent *n)
   25: {
   26:   xstr os, ns;
   27:   int res;
   28:   int o_idx = o->core_elm_index;
   29:   int n_idx = n->core_elm_index;
   30: 
   31:   /* 自立語部を含む文節しか学習しない */
   32:   if (o_idx < 0 || n_idx < 0) {
   33:     return ;
   34:   }
   35:   if (o->elm[o_idx].str.len != n->elm[n_idx].str.len) {
   36:     return ;
   37:   }
   38:   if (o->elm[o_idx].nth == -1 || n->elm[n_idx].nth == -1) {
   39:     return ;
   40:   }
   41:   res = anthy_get_nth_dic_ent_str(o->elm[o_idx].se, &o->elm[o_idx].str,
   42:                                   o->elm[o_idx].nth, &os);
   43:   if (res) {
   44:     return ;
   45:   }
   46:   res = anthy_get_nth_dic_ent_str(n->elm[n_idx].se, &n->elm[n_idx].str,
   47:                                   n->elm[n_idx].nth, &ns);
   48:   if (res) {
   49:     free(os.str);
   50:     return ;
   51:   }
   52:   if (anthy_select_section("INDEPPAIR", 1) == 0) {
   53:     if (anthy_select_row(&os, 1) == 0) {
   54:       anthy_set_nth_xstr(0, &ns);
   55:     }
   56:   }
   57:   free(os.str);
   58:   free(ns.str);
   59: }
   60: 
   61: /*
   62:  * 候補o を出したらn がコミットされたので
   63:  * o -> n をrecordにセットする
   64:  */
   65: void
   66: anthy_swap_cand_ent(struct cand_ent *o, struct cand_ent *n)
   67: {
   68:   if (o == n) {
   69:     /* 同じ候補 */
   70:     return ;
   71:   }
   72:   if (n->flag & CEF_USEDICT) {
   73:     /* 用例辞書から出てきた候補 */
   74:     return ;
   75:   }
   76:   /* 自立語部 */
   77:   learn_swap_cand_indep(o, n);
   78: }
   79: 
   80: 
   81: /*
   82:  * 変換時に生成した候補を並べた状態で最優先の候補を決める
   83:  * ループの除去なども行う
   84:  */
   85: static xstr *
   86: prepare_swap_candidate(xstr *target)
   87: {
   88:   xstr *xs, *n;
   89:   if (anthy_select_row(target, 0) == -1) {
   90:     return NULL;
   91:   }
   92:   xs = anthy_get_nth_xstr(0);
   93:   if (!xs) {
   94:     return NULL;
   95:   }
   96:   /* 第一候補 -> xs となるのを発見 */
   97:   anthy_mark_row_used();
   98:   if (anthy_select_row(xs, 0) != 0){
   99:     /* xs -> ⊥ */
  100:     return xs;
  101:   }
  102:   /* xs -> n */
  103:   n = anthy_get_nth_xstr(0);
  104:   if (!n) {
  105:     return NULL;
  106:   }
  107: 
  108:   if (!anthy_xstrcmp(target, n)) {
  109:     /* 第一候補 -> xs -> n で n = 第一候補のループ */
  110:     anthy_select_row(target, 0);
  111:     anthy_release_row();
  112:     anthy_select_row(xs, 0);
  113:     anthy_release_row();
  114:     /* 第一候補 -> xs を消して、交換の必要は無し */
  115:     return NULL;
  116:   }
  117:   /* 第一候補 -> xs -> n で n != 第一候補なので
  118:    * 第一候補 -> nを設定
  119:    */
  120:   if (anthy_select_row(target, 0) == 0){
  121:     anthy_set_nth_xstr(0, n);
  122:   }
  123:   return n;
  124: }
  125: 
  126: #include <src-worddic/dic_ent.h>
  127: 
  128: /*
  129:  * 自立語のみ
  130:  */
  131: static void
  132: proc_swap_candidate_indep(struct seg_ent *se)
  133: {
  134:   xstr *xs;
  135:   xstr key;
  136:   int i;
  137:   int core_elm_idx;
  138:   int res;
  139:   struct cand_elm *core_elm;
  140: 
  141:   core_elm_idx = se->cands[0]->core_elm_index;
  142:   if (core_elm_idx < 0) {
  143:     return ;
  144:   }
  145: 
  146:   /* 0番目の候補の文字列を取り出す */
  147:   core_elm = &se->cands[0]->elm[core_elm_idx];
  148:   if (core_elm->nth < 0) {
  149:     return ;
  150:   }
  151:   res = anthy_get_nth_dic_ent_str(core_elm->se,
  152:                                   &core_elm->str,
  153:                                   core_elm->nth,
  154:                                   &key);
  155:   if (res) {
  156:     return ;
  157:   }
  158: 
  159:   /**/
  160:   anthy_select_section("INDEPPAIR", 1);
  161:   xs = prepare_swap_candidate(&key);
  162:   free(key.str);
  163:   if (!xs) {
  164:     return ;
  165:   }
  166: 
  167:   /* 第一候補 -> xs なので xsの候補を探す */
  168:   for (i = 1; i < se->nr_cands; i++) {
  169:     if (se->cands[i]->nr_words == se->cands[0]->nr_words &&
  170:         se->cands[i]->core_elm_index == core_elm_idx) {
  171:       xstr cand;
  172:       res = anthy_get_nth_dic_ent_str(se->cands[i]->elm[core_elm_idx].se,
  173:                                       &se->cands[i]->elm[core_elm_idx].str,
  174:                                       se->cands[i]->elm[core_elm_idx].nth,
  175:                                       &cand);
  176:       if (res == 0 &&
  177:           !anthy_xstrcmp(&cand, xs)) {
  178:         free(cand.str);
  179:         /* みつけたのでその候補のスコアをアップ */
  180:         se->cands[i]->score = se->cands[0]->score + 1;
  181:         return ;
  182:       }
  183:       free(cand.str);
  184:     }
  185:   }
  186: }
  187: 
  188: /*
  189:  * 変換時に生成した候補を並べた状態で最優先の候補を決める
  190:  */
  191: void
  192: anthy_proc_swap_candidate(struct seg_ent *seg)
  193: {
  194: 
  195:   if (seg->cands[0]->score >= OCHAIRE_SCORE) {
  196:     /* cands[0] は特別な点数を持っている */
  197:     return ;
  198:   }
  199:   if (seg->cands[0]->flag & CEF_USEDICT) {
  200:     return ;
  201:   }
  202:   /**/
  203:   proc_swap_candidate_indep(seg);
  204: }
  205: 
  206: /* 候補交換の古いエントリを消す */
  207: void
  208: anthy_cand_swap_ageup(void)
  209: {
  210:   if (anthy_select_section("INDEPPAIR", 0) == 0) {
  211:     anthy_truncate_section(MAX_INDEP_PAIR_ENTRY);
  212:   }
  213: }
Syntax (Markdown)