package ruc.irm.similarity.word.hownet2.sememe; import java.io.IOException; import java.util.Collection; import ruc.irm.similarity.util.BlankUtils; /** * 义原相似度计算, 实现了SememeParser中定义的抽象方法 * * @author <a href="mailto:iamxiatian@gmail.com">夏天</a> * @organization 中国人民大学信息资源管理学院 知识工程实验室 */ public class XiaSememeParser extends BaseSememeParser { public XiaSememeParser() throws IOException{ super(); } /** * 计算两个义原的相似度 */ double getSimilarityBySememeId(final String id1, final String id2) { int position = 0; String[] array1 = id1.split("-"); String[] array2 = id2.split("-"); for (position = 0; position < array1.length && position < array2.length; position++) { if (!array1[position].equals(array2[position])) { break; } } return 2.0*position/(array1.length + array2.length); } /** * 根据汉语定义计算义原之间的相似度,由于可能多个义元有相同的汉语词语,故计算结果为其中相似度最大者 * * @param key1 * @param key2 * @return */ public double getMaxSimilarity(String sememeName1, String sememeName2) { double maxValue = 0.0; // 如果两个字符串相等,直接返回距离为0 if (sememeName1.equals(sememeName2)) { return 1.0; } Collection<String> sememeIds1 = SEMEMES.get(sememeName1); Collection<String> sememeIds2 = SEMEMES.get(sememeName2); // 如果sememe1或者sememe2不是义元,则返回0 if (sememeIds1.size() == 0 || sememeIds1.size() == 0) { return 0.0; } for(String id1:sememeIds1){ for(String id2:sememeIds2){ double value = getSimilarityBySememeId(id1, id2); if(value > maxValue){ maxValue = value; } } } return maxValue; } /** * 计算两个义元之间的相似度,由于义元可能相同,计算结果为其中相似度最大者 similarity = alpha/(distance+alpha), * 如果两个字符串相同或都为空,直接返回1.0 * * @param key1 第一个义原字符串 * @param key2 第二个义原字符串 * @return */ @Override public double getSimilarity(String item1, String item2) { if(BlankUtils.isBlankAll(item2, item2)){ return 1.0; } else if(BlankUtils.isBlankAtLeastOne(item1, item2)){ return 0.0; } else if(item1.equals(item2)){ return 1.0; } String key1 = item1.trim(); String key2 = item2.trim(); // 去掉()符号 if ((key1.charAt(0) == '(') && (key1.charAt(key1.length() - 1) == ')')) { if (key2.charAt(0) == '(' && key2.charAt(key2.length() - 1) == ')') { key1 = key1.substring(1, key1.length() - 1); key2 = key2.substring(1, key2.length() - 1); } else { return 0.0; } } // 处理关系义元,即x=y的情况 int pos = key1.indexOf('='); if (pos > 0) { int pos2 = key2.indexOf('='); // 如果是关系义元,则判断前面部分是否相同,如果相同,则转为计算后面部分的相似度,否则为0 if ((pos == pos2) && key1.substring(0, pos).equals(key2.substring(0, pos2))) { key1 = key1.substring(pos + 1); key2 = key2.substring(pos2 + 1); } else { return 0.0; } } // 处理符号义元,即前面有特殊符号的义元 String symbol1 = key1.substring(0, 1); String symbol2 = key2.substring(0, 1); for (int i = 0; i < Symbol_Descriptions.length; i++) { if (symbol1.equals(Symbol_Descriptions[i][0])) { if (symbol1.equals(symbol2)) { key1 = item1.substring(1); key2 = item2.substring(1); break; } else { return 0.0; // 如果不是同一关系符号,则相似度直接返回0 } } } if ((pos = key1.indexOf("|")) >= 0) { key1 = key1.substring(pos + 1); } if ((pos = key2.indexOf("|")) >= 0) { key2 = key2.substring(pos + 1); } // 如果两个字符串相等,直接返回距离为0 if (key1.equals(key2)) { return 1.0; } return getMaxSimilarity(key1, key2); } }