|
@@ -0,0 +1,211 @@
|
|
|
+package org.algorithm.core;
|
|
|
+
|
|
|
+import org.algorithm.core.cnn.entity.Lemma;
|
|
|
+import org.algorithm.core.cnn.entity.Triad;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 关系树工具类
|
|
|
+ *
|
|
|
+ * @Author: bijl
|
|
|
+ * @Date: 2019/9/5 15:16
|
|
|
+ * @Description:
|
|
|
+ */
|
|
|
+public class RelationTreeUtils {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同名实体(这里也叫词项)归并
|
|
|
+ * 规则:
|
|
|
+ * 1- 直接替代为位置最前面的一个
|
|
|
+ *
|
|
|
+ * @param triads 实体对列表
|
|
|
+ */
|
|
|
+ public static void sameTextLemmaMerge(List<Triad> triads) {
|
|
|
+
|
|
|
+ Map<String, Lemma> lemmaMap = new HashMap<>();
|
|
|
+ for (Triad triad : triads) {
|
|
|
+ Lemma l1 = triad.getL_1();
|
|
|
+ Lemma l2 = triad.getL_2();
|
|
|
+
|
|
|
+ if (lemmaMap.get(l1.getText()) == null)
|
|
|
+ lemmaMap.put(l1.getText(), l1);
|
|
|
+ else {
|
|
|
+ Lemma l1Pre = lemmaMap.get(l1.getText());
|
|
|
+ if (l1Pre.getStartPosition() > l1.getStartPosition())
|
|
|
+ triad.setL_1(l1); // 取靠前的
|
|
|
+ }
|
|
|
+
|
|
|
+ if (lemmaMap.get(l2.getText()) == null)
|
|
|
+ lemmaMap.put(l2.getText(), l2);
|
|
|
+ else {
|
|
|
+ Lemma l2Pre = lemmaMap.get(l2.getText());
|
|
|
+ if (l2Pre.getStartPosition() > l2.getStartPosition())
|
|
|
+ triad.setL_2(l2); // 取靠前的
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (Triad triad : triads) {
|
|
|
+ Lemma l1 = triad.getL_1();
|
|
|
+ Lemma l2 = triad.getL_2();
|
|
|
+ triad.setL_1(lemmaMap.get(l1.getText())); // 用前面的同名实体(这里也叫词项)替代后面的
|
|
|
+ triad.setL_2(lemmaMap.get(l2.getText())); // 用前面的同名实体(这里也叫词项)替代后面的
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建关系树
|
|
|
+ * 基本规则:
|
|
|
+ * 1- 两个有关系的实体,前面的为父节点,后面的为子节点
|
|
|
+ *
|
|
|
+ * @param triads 有关系的三元组列表
|
|
|
+ */
|
|
|
+ public static void buildRelationTree(List<Triad> triads) {
|
|
|
+ for (Triad triad : triads) {
|
|
|
+ Lemma l1 = triad.getL_1();
|
|
|
+ Lemma l2 = triad.getL_2();
|
|
|
+ if (l1.getStartPosition() < l2.getStartPosition()) { // 在前者为父节点
|
|
|
+ l1.setHasChildren(true);
|
|
|
+ l2.setParent(l1);
|
|
|
+ } else {
|
|
|
+ l2.setHasChildren(true);
|
|
|
+ l1.setParent(l2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取关系树的分枝
|
|
|
+ *
|
|
|
+ * @param projectName 项目名称,如:核磁共振
|
|
|
+ * @param triads 有关系,并且设置了父子节点关系的三元组
|
|
|
+ */
|
|
|
+ public static Object[] getRelationTreeBranches(String projectName, List<Triad> triads) {
|
|
|
+ List<Lemma> hasNoChildrenLemmas = new ArrayList<>();
|
|
|
+ for (Triad triad : triads) {
|
|
|
+ if (!triad.getL_1().isHasChildren())
|
|
|
+ hasNoChildrenLemmas.add(triad.getL_1());
|
|
|
+
|
|
|
+ if (!triad.getL_2().isHasChildren())
|
|
|
+ hasNoChildrenLemmas.add(triad.getL_2());
|
|
|
+ }
|
|
|
+
|
|
|
+ List<List<String>> branches = new ArrayList<>();
|
|
|
+ for (Lemma lemma : hasNoChildrenLemmas) {
|
|
|
+ List<String> aBranch = new ArrayList<>();
|
|
|
+ while (lemma != null) {
|
|
|
+ aBranch.add(lemma.getText()); // 只加入,文本
|
|
|
+ lemma = lemma.getParent();
|
|
|
+ }
|
|
|
+ branches.addAll(permute(aBranch)); // 排列
|
|
|
+ }
|
|
|
+
|
|
|
+ Object[] obj = {projectName, branches};
|
|
|
+
|
|
|
+ return obj;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从三元组列表到关系树分枝
|
|
|
+ *
|
|
|
+ * @param projectName
|
|
|
+ * @param triads
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static Object[] triadsToRelationTreeBranches(String projectName, List<Triad> triads) {
|
|
|
+ sameTextLemmaMerge(triads);
|
|
|
+ buildRelationTree(triads);
|
|
|
+ Object[] obj = getRelationTreeBranches("胃造影", triads);
|
|
|
+ return obj;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 全排列算法
|
|
|
+ *
|
|
|
+ * @param stringList 字符串列表
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static ArrayList<ArrayList<String>> permute(List<String> stringList) {
|
|
|
+ ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();
|
|
|
+ result.add(new ArrayList<String>());
|
|
|
+
|
|
|
+ for (int i = 0; i < stringList.size(); i++) {
|
|
|
+ //list of list in current iteration of the stringList num
|
|
|
+ ArrayList<ArrayList<String>> current = new ArrayList<ArrayList<String>>();
|
|
|
+
|
|
|
+ for (ArrayList<String> l : result) {
|
|
|
+ // # of locations to insert is largest index + 1
|
|
|
+ for (int j = 0; j < l.size() + 1; j++) {
|
|
|
+ // + add num[i] to different locations
|
|
|
+ l.add(j, stringList.get(i));
|
|
|
+
|
|
|
+ ArrayList<String> temp = new ArrayList<String>(l);
|
|
|
+ current.add(temp);
|
|
|
+
|
|
|
+ // - remove num[i] add
|
|
|
+ l.remove(j);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ result = new ArrayList<ArrayList<String>>(current);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试文件
|
|
|
+ */
|
|
|
+ public static void test() {
|
|
|
+
|
|
|
+ List<Triad> triads = new ArrayList<>();
|
|
|
+ Lemma l1_1 = new Lemma();
|
|
|
+ Lemma l1_2 = new Lemma();
|
|
|
+ l1_1.setText("子宫");
|
|
|
+ l1_1.setPosition("0,2");
|
|
|
+
|
|
|
+ l1_2.setText("内膜");
|
|
|
+ l1_2.setPosition("5,8");
|
|
|
+
|
|
|
+ Triad triad_1 = new Triad();
|
|
|
+ triad_1.setL_1(l1_1);
|
|
|
+ triad_1.setL_2(l1_2);
|
|
|
+ triads.add(triad_1);
|
|
|
+
|
|
|
+ Lemma l2_1 = new Lemma();
|
|
|
+ Lemma l2_2 = new Lemma();
|
|
|
+ l2_1.setText("宫颈线");
|
|
|
+ l2_1.setPosition("11,13");
|
|
|
+
|
|
|
+ l2_2.setText("很长");
|
|
|
+ l2_2.setPosition("15,18");
|
|
|
+
|
|
|
+ Triad triad_2 = new Triad();
|
|
|
+ triad_2.setL_1(l2_1);
|
|
|
+ triad_2.setL_2(l2_2);
|
|
|
+ triads.add(triad_2);
|
|
|
+
|
|
|
+
|
|
|
+ Lemma l3_1 = new Lemma();
|
|
|
+ Lemma l3_2 = new Lemma();
|
|
|
+
|
|
|
+ l3_1.setText("内膜");
|
|
|
+ l3_1.setPosition("5,8");
|
|
|
+
|
|
|
+ l3_2.setText("出血");
|
|
|
+ l3_2.setPosition("9,10");
|
|
|
+
|
|
|
+ Triad triad_3 = new Triad();
|
|
|
+ triad_3.setL_1(l3_1);
|
|
|
+ triad_3.setL_2(l3_2);
|
|
|
+ triads.add(triad_3);
|
|
|
+
|
|
|
+ sameTextLemmaMerge(triads);
|
|
|
+ buildRelationTree(triads);
|
|
|
+ Object[] obj = getRelationTreeBranches("胃造影", triads);
|
|
|
+
|
|
|
+ System.out.println(obj[0]);
|
|
|
+ System.out.println(obj[1]);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|