/*
 * <summary></summary>
 * <author>He Han</author>
 * <email>hankcs.cn@gmail.com</email>
 * <create-date>2014/05/2014/5/26 13:52</create-date>
 *
 * <copyright file="UnknowWord.java" company="上海林原信息科技有限公司">
 * Copyright (c) 2003-2014, 上海林原信息科技有限公司. All Right Reserved, http://www.linrunsoft.com/
 * This source is subject to the LinrunSpace License. Please contact 上海林原信息科技有限公司 to get more information.
 * </copyright>
 */
package com.hankcs.hanlp.recognition.nr;

import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.algoritm.Viterbi;
import com.hankcs.hanlp.corpus.dictionary.item.EnumItem;
import com.hankcs.hanlp.corpus.tag.NR;
import com.hankcs.hanlp.corpus.tag.Nature;
import com.hankcs.hanlp.dictionary.nr.PersonDictionary;
import com.hankcs.hanlp.seg.common.Vertex;
import com.hankcs.hanlp.seg.common.WordNet;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * 人名识别
 * @author hankcs
 */
public class PersonRecognition
{
    public static boolean Recognition(List<Vertex> pWordSegResult, WordNet wordNetOptimum, WordNet wordNetAll)
    {
        List<EnumItem<NR>> roleTagList = roleTag(pWordSegResult);
        if (HanLP.Config.DEBUG)
        {
            StringBuilder sbLog = new StringBuilder();
            Iterator<Vertex> iterator = pWordSegResult.iterator();
            for (EnumItem<NR> nrEnumItem : roleTagList)
            {
                sbLog.append('[');
                sbLog.append(iterator.next().realWord);
                sbLog.append(' ');
                sbLog.append(nrEnumItem);
                sbLog.append(']');
            }
            System.out.printf("人名角色观察：%s\n", sbLog.toString());
        }
        List<NR> nrList = viterbiExCompute(roleTagList);
        if (HanLP.Config.DEBUG)
        {
            StringBuilder sbLog = new StringBuilder();
            Iterator<Vertex> iterator = pWordSegResult.iterator();
            sbLog.append('[');
            for (NR nr : nrList)
            {
                sbLog.append(iterator.next().realWord);
                sbLog.append('/');
                sbLog.append(nr);
                sbLog.append(" ,");
            }
            if (sbLog.length() > 1) sbLog.delete(sbLog.length() - 2, sbLog.length());
            sbLog.append(']');
            System.out.printf("人名角色标注：%s\n", sbLog.toString());
        }

        PersonDictionary.parsePattern(nrList, pWordSegResult, wordNetOptimum, wordNetAll);
        return true;
    }

    public static List<EnumItem<NR>> roleTag(List<Vertex> pWordSegResult)
    {
        List<EnumItem<NR>> tagList = new LinkedList<EnumItem<NR>>();
        for (Vertex vertex : pWordSegResult)
        {
            EnumItem<NR> nrEnumItem = PersonDictionary.dictionary.get(vertex.realWord);
            if (nrEnumItem == null)
            {
                switch (vertex.guessNature())
                {
                    case nr:
                    {
                        // 有些双名实际上可以构成更长的三名
                        if (vertex.getAttribute().totalFrequency <= 1000)
                        {
                            if (vertex.realWord.length() == 2)
                            {
                                nrEnumItem = new EnumItem<NR>(NR.X, NR.G);
                            }
                            else nrEnumItem = new EnumItem<NR>(NR.A, PersonDictionary.transformMatrixDictionary.getTotalFrequency(NR.A));
                        }
                    }break;
                    case nnt:
                    {
                        // 姓+职位
                        nrEnumItem = new EnumItem<NR>(NR.G, NR.K);
                    }break;
                    default:
                    {
                        nrEnumItem = new EnumItem<NR>(NR.A, PersonDictionary.transformMatrixDictionary.getTotalFrequency(NR.A));
                    }break;
                }
            }
            tagList.add(nrEnumItem);
        }
        return tagList;
    }

    /**
     * 维特比算法求解最优标签
     * @param roleTagList
     * @return
     */
    public static List<NR> viterbiCompute(List<EnumItem<NR>> roleTagList)
    {
        List<NR> resultList = new LinkedList<NR>();
        // HMM五元组
        int[] observations = new int[roleTagList.size()];
        for (int i = 0; i < observations.length; ++i)
        {
            observations[i] = i;
        }
        double[][] emission_probability = new double[PersonDictionary.transformMatrixDictionary.ordinaryMax][observations.length];
        for (int i = 0; i < emission_probability.length; ++i)
        {
            for (int j = 0; j < emission_probability[i].length; ++j)
            {
                emission_probability[i][j] = 1e8;
            }
        }
        for (int s : PersonDictionary.transformMatrixDictionary.states)
        {
            Iterator<EnumItem<NR>> iterator = roleTagList.iterator();
            for (int o : observations)
            {
                NR sNR = NR.values()[s];
                EnumItem<NR> item = iterator.next();
                double frequency = item.getFrequency(sNR);
                if (frequency == 0)
                {
                    emission_probability[s][o] = 1e8;
                }
                else
                {
                    emission_probability[s][o] = -Math.log(frequency / PersonDictionary.transformMatrixDictionary.getTotalFrequency(sNR));
                }

            }
        }
        int[] result = Viterbi.compute(observations,
                                        PersonDictionary.transformMatrixDictionary.states,
                                        PersonDictionary.transformMatrixDictionary.start_probability,
                                        PersonDictionary.transformMatrixDictionary.transititon_probability,
                                        emission_probability
        );
        for (int r : result)
        {
            resultList.add(NR.values()[r]);
        }
        return resultList;
    }

    /**
     * 维特比算法求解最优标签
     * @param roleTagList
     * @return
     */
    public static List<NR> viterbiExCompute(List<EnumItem<NR>> roleTagList)
    {
        return Viterbi.computeEnumSimply(roleTagList, PersonDictionary.transformMatrixDictionary);
    }
}

@@ -3033,68 +3033,12 @@
 1000
-)%0A                        %7B%0A                            if (
+ && 
 vert
@@ -3064,20 +3064,16 @@
 ) == 2)%0A
-    
         
@@ -3110,36 +3110,32 @@
                 
-    
 nrEnumItem = new
@@ -3181,34 +3181,26 @@
             
-    %7D%0A    
+%7D%0A
             
@@ -3325,34 +3325,8 @@
 ));%0A
-                        %7D%0A
     

修复人名识别模块的问题:https://github.com/hankcs/HanLP/issues/151