浏览代码

dev分支合并入当前分支

louhr 5 年之前
父节点
当前提交
6285135b58
共有 50 个文件被更改,包括 2152 次插入350 次删除
  1. 130 0
      algorithm/src/main/java/org/algorithm/core/FilterRule.java
  2. 282 0
      algorithm/src/main/java/org/algorithm/core/RelationTreeUtils.java
  3. 493 0
      algorithm/src/main/java/org/algorithm/core/RuleCheckMachine.java
  4. 3 4
      algorithm/src/main/java/org/algorithm/core/cnn/AlgorithmCNNExecutor.java
  5. 22 0
      algorithm/src/main/java/org/algorithm/core/cnn/AlgorithmCNNExecutorPacs.java
  6. 1 1
      algorithm/src/main/java/org/algorithm/core/cnn/dataset/RelationExtractionDataSet.java
  7. 32 1
      algorithm/src/main/java/org/algorithm/core/cnn/entity/Lemma.java
  8. 40 13
      algorithm/src/main/java/org/algorithm/core/cnn/model/RelationExtractionEnsembleModel.java
  9. 4 4
      algorithm/src/main/java/org/algorithm/core/cnn/model/RelationExtractionModel.java
  10. 2 1
      algorithm/src/main/java/org/algorithm/core/neural/DiagnosisPredictExecutor.java
  11. 30 7
      algorithm/src/main/java/org/algorithm/core/neural/TensorFlowModelLoadFactory.java
  12. 122 13
      algorithm/src/main/java/org/algorithm/core/neural/dataset/NNDataSet.java
  13. 113 73
      algorithm/src/main/java/org/algorithm/core/neural/dataset/NNDataSetImpl.java
  14. 11 1
      algorithm/src/main/java/org/algorithm/core/neural/dataset/NNDataSetImplNonParallel.java
  15. 33 0
      algorithm/src/main/java/org/algorithm/factory/RelationExtractionFactory.java
  16. 5 3
      algorithm/src/main/java/org/algorithm/test/ReEnsembleModelTest.java
  17. 9 4
      algorithm/src/main/java/org/algorithm/test/TensorflowExcutorTest.java
  18. 47 40
      algorithm/src/main/java/org/algorithm/test/Test.java
  19. 46 0
      algorithm/src/main/java/org/algorithm/test/TestDiagnosisFilter.java
  20. 34 0
      algorithm/src/main/java/org/algorithm/test/TestReSplit.java
  21. 15 0
      algorithm/src/main/java/org/algorithm/test/TestRelationTreeUtils.java
  22. 140 0
      algorithm/src/main/java/org/algorithm/test/TestRuleCheckMachine.java
  23. 1 1
      algorithm/src/main/java/org/algorithm/util/MysqlConnector.java
  24. 1 1
      algorithm/src/main/resources/algorithm.properties
  25. 34 0
      common-push/src/main/java/org/diagbot/common/push/cache/ApplicationCacheUtil.java
  26. 21 28
      common-push/src/main/java/org/diagbot/common/push/cache/CacheFileManager.java
  27. 16 42
      common-push/src/main/java/org/diagbot/common/push/filter/ClassifyDiag.java
  28. 2 0
      common-push/src/main/java/org/diagbot/common/push/filter/pretreat/Pretreatment.java
  29. 39 5
      common-push/src/main/java/org/diagbot/common/push/filter/pretreat/PretreatmentLis.java
  30. 83 6
      common-push/src/main/java/org/diagbot/common/push/filter/pretreat/PretreatmentPacs.java
  31. 22 0
      common-push/src/main/java/org/diagbot/common/push/util/PushConstants.java
  32. 15 23
      common-push/src/main/java/org/diagbot/common/push/work/ParamsDataProxy.java
  33. 92 0
      common-push/src/main/java/org/diagbot/common/push/work/RelationExtractionUtil.java
  34. 6 0
      graph-web/src/main/java/org/diagbot/graphWeb/work/GraphCalculate.java
  35. 1 1
      graph-web/src/main/java/org/diagbot/graphWeb/work/ScaleCalculate.java
  36. 1 1
      graph/src/main/resources/bolt.properties
  37. 3 3
      graphdb/src/main/java/org/diagbot/service/impl/KnowledgeServiceImpl.java
  38. 1 1
      graphdb/src/main/resources/application.yml
  39. 60 51
      nlp-web/src/main/java/org/diagbot/nlp/controller/FeatureController.java
  40. 1 1
      nlp-web/src/main/java/org/diagbot/nlp/dao/xml/InfoMapper.xml
  41. 1 1
      nlp-web/src/main/resources/application.yml
  42. 7 0
      nlp/src/main/java/org/diagbot/nlp/feature/FeatureAnalyze.java
  43. 31 2
      nlp/src/main/java/org/diagbot/nlp/feature/extract/CaseToken.java
  44. 33 15
      nlp/src/main/java/org/diagbot/nlp/participle/ParticipleUtil.java
  45. 14 0
      nlp/src/main/java/org/diagbot/nlp/util/NlpCache.java
  46. 4 1
      nlp/src/main/resources/nlp.properties
  47. 14 2
      push-web/src/main/java/org/diagbot/push/controller/AlgorithmController.java
  48. 2 0
      push-web/src/main/java/org/diagbot/push/controller/CacheFileManagerController.java
  49. 11 0
      push-web/src/main/java/org/diagbot/push/controller/ParticipleController.java
  50. 22 0
      rule/src/main/java/org/diagbot/rule/crisis/CrisisApplication.java

+ 130 - 0
algorithm/src/main/java/org/algorithm/core/FilterRule.java

@@ -0,0 +1,130 @@
+package org.algorithm.core;
+
+import java.util.Map;
+
+/**
+ * 过滤规则
+ *
+ * @Author: bijl
+ * @Date: 2019/9/5 20:21
+ * @Description:
+ */
+public class FilterRule {
+
+    private Integer uuid;
+
+    private String key_1;
+    private String type_1;
+
+    private String key_2;
+    private String type_2;
+
+    private String inside;
+    private String insideType;
+
+    private String despite;
+    private String despiteInside;
+
+    public FilterRule(Map<String, String> aMap) {
+
+        this.key_1 = aMap.get("key_1");
+        this.type_1 = aMap.get("type_1");
+
+        this.key_2 = aMap.get("key_2");
+        this.type_2 = aMap.get("type_2");
+
+        this.inside = aMap.get("inside");
+        this.insideType = aMap.get("inside_type");
+
+        this.despite = aMap.get("despite");
+        this.despiteInside = aMap.get("despite_inside");
+    }
+
+    public Integer getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(Integer uuid) {
+        this.uuid = uuid;
+    }
+
+
+    public String getKey_1() {
+        return key_1;
+    }
+
+    public void setKey_1(String key_1) {
+        this.key_1 = key_1;
+    }
+
+    public String getType_1() {
+        return type_1;
+    }
+
+    public void setType_1(String type_1) {
+        this.type_1 = type_1;
+    }
+
+    public String getKey_2() {
+        return key_2;
+    }
+
+    public void setKey_2(String key_2) {
+        this.key_2 = key_2;
+    }
+
+    public String getType_2() {
+        return type_2;
+    }
+
+    public void setType_2(String type_2) {
+        this.type_2 = type_2;
+    }
+
+    public String getInside() {
+        return inside;
+    }
+
+    public void setInside(String inside) {
+        this.inside = inside;
+    }
+
+    public String getInsideType() {
+        return insideType;
+    }
+
+    public void setInsideType(String insideType) {
+        this.insideType = insideType;
+    }
+
+    public String getDespite() {
+        return despite;
+    }
+
+    public void setDespite(String despite) {
+        this.despite = despite;
+    }
+
+    public String getDespiteInside() {
+        return despiteInside;
+    }
+
+    public void setDespiteInside(String despiteInside) {
+        this.despiteInside = despiteInside;
+    }
+
+    @Override
+    public String toString() {
+        return "FilterRule{" +
+                "uuid=" + uuid +
+                ", key_1='" + key_1 + '\'' +
+                ", type_1='" + type_1 + '\'' +
+                ", key_2='" + key_2 + '\'' +
+                ", type_2='" + type_2 + '\'' +
+                ", inside='" + inside + '\'' +
+                ", insideType='" + insideType + '\'' +
+                ", despite='" + despite + '\'' +
+                ", despiteInside='" + despiteInside + '\'' +
+                '}';
+    }
+}

+ 282 - 0
algorithm/src/main/java/org/algorithm/core/RelationTreeUtils.java

@@ -0,0 +1,282 @@
+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.setHaveChildren(true);
+                l2.setParent(l1);
+            } else {
+                l2.setHaveChildren(true);
+                l1.setParent(l2);
+            }
+        }
+    }
+
+    /**
+     * 获取关系树的分枝
+     *
+     * @param triads 有关系,并且设置了父子节点关系的三元组
+     */
+    public static List<List<String>> getRelationTreeBranches(List<Triad> triads) {
+        Map<Lemma, Integer> leafNodeLemmas = new HashMap<>();
+
+        for (Triad triad : triads) {
+            if (!triad.getL_1().isHaveChildren())
+                leafNodeLemmas.putIfAbsent(triad.getL_1(), 1);
+
+            if (!triad.getL_2().isHaveChildren())
+                leafNodeLemmas.putIfAbsent(triad.getL_2(), 1);
+        }
+
+        List<List<String>> branches = new ArrayList<>();
+        for (Lemma lemma : leafNodeLemmas.keySet()) {
+            List<Lemma> aBranch = new ArrayList<>();
+            while (lemma != null) {
+                aBranch.add(lemma);
+                lemma = lemma.getParent();
+            }
+            aBranch.sort(Comparator.naturalOrder());  // 按位置排序
+            branches.addAll(handleBranch(aBranch));
+        }
+
+
+        return branches;
+    }
+
+    /**
+     * 处理分枝,要求组合非阴性词,阴性词必须包含
+     * 操作:
+     * 1- 分离阴性词和非阴性词
+     * 2- 组合非阴性词
+     * 3- 添加阴性词到组合结果中
+     *
+     * @param aBranch
+     * @return
+     */
+    private static List<List<String>> handleBranch(List<Lemma> aBranch) {
+        List<Lemma> nonNegativeLemmas = new ArrayList<>();
+        List<Lemma> negativeLemmas = new ArrayList<>();
+        for (Lemma lemma : aBranch) {
+            if ("反意或虚拟".equals(lemma.getProperty()))
+                negativeLemmas.add(lemma);
+            else
+                nonNegativeLemmas.add(lemma);
+        }
+        List<List<Lemma>> nonNegativeLemmaCombinations = new ArrayList<>();
+        if (nonNegativeLemmas.size() > 0) {
+            for (int i = 1; i <= nonNegativeLemmas.size(); i++) {
+                combinerSelect(nonNegativeLemmas, new ArrayList<>(), nonNegativeLemmaCombinations,
+                        nonNegativeLemmas.size(), i);
+            }
+        }
+        List<List<String>> result = new ArrayList<>();
+        for (List<Lemma> lemmaCombination : nonNegativeLemmaCombinations) {
+            List<String> lemmaNames = new ArrayList<>();
+            lemmaCombination.addAll(negativeLemmas);  // 阴性词加入到组合中
+            lemmaCombination.sort(Comparator.naturalOrder());  // 按位置排序
+            for (Lemma lemma : lemmaCombination)  // 取出名称
+                lemmaNames.add(lemma.getText());
+            if (lemmaNames.size() >= 2)
+                result.add(lemmaNames);
+        }
+
+        return result;
+
+    }
+
+    /**
+     * 从三元组列表到关系树分枝
+     *
+     * @param triads
+     * @return
+     */
+    public static List<List<String>> triadsToRelationTreeBranches(List<Triad> triads) {
+//        sameTextLemmaMerge(triads);
+        buildRelationTree(triads);
+        return getRelationTreeBranches(triads);
+    }
+
+    /**
+     * 组合生成器
+     *
+     * @param data      原始数据
+     * @param workSpace 自定义一个临时空间,用来存储每次符合条件的值
+     * @param k         C(n,k)中的k
+     */
+    private static <E> void combinerSelect(List<E> data, List<E> workSpace, List<List<E>> result, int n, int k) {
+        List<E> copyData;
+        List<E> copyWorkSpace = null;
+
+        if (workSpace.size() == k) {
+//            for (E c : workSpace)
+//                System.out.print(c);
+
+            result.add(new ArrayList<>(workSpace));
+//            System.out.println();
+        }
+
+        for (int i = 0; i < data.size(); i++) {
+            copyData = new ArrayList<E>(data);
+            copyWorkSpace = new ArrayList<E>(workSpace);
+
+            copyWorkSpace.add(copyData.get(i));
+            for (int j = i; j >= 0; j--)
+                copyData.remove(j);
+            combinerSelect(copyData, copyWorkSpace, result, n, k);
+        }
+    }
+
+    /**
+     * 全排列算法
+     *
+     * @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<>(current);
+        }
+
+        return result;
+    }
+
+
+    /**
+     * 测试文件
+     */
+    public static void test() {
+
+        List<Triad> triads = new ArrayList<>();
+        String[] arr_1 = {"子宫", "0,1", "部位"};
+        String[] arr_2 = {"内膜", "2,3", "结构"};
+        addTriad(arr_1, arr_2, triads);
+
+        String[] arr_1_1 = {"不", "13,13", "反意或虚拟"};
+        String[] arr_2_1 = {"出血", "10,11", "形容词"};
+        addTriad(arr_1_1, arr_2_1, triads);
+
+        String[] arr_1_2 = {"胸部", "15,16", "部位"};
+        String[] arr_2_2 = {"剧烈", "17,18", "程度"};
+        addTriad(arr_1_2, arr_2_2, triads);
+
+        String[] arr_1_3 = {"疼痛", "17,18", "形容词"};
+        String[] arr_2_3 = {"剧烈", "19,20", "程度"};
+        addTriad(arr_1_3, arr_2_3, triads);
+
+        String[] arr_1_4 = {"内膜", "2,3", "结构"};
+        String[] arr_2_4 = {"出血", "10,11", "形容词"};
+        addTriad(arr_1_4, arr_2_4, triads);
+
+        System.out.println(triads.size());
+        sameTextLemmaMerge(triads);
+        buildRelationTree(triads);
+        List<List<String>> info = getRelationTreeBranches(triads);
+
+        System.out.println(info);
+    }
+
+    /**
+     * 增加三元组
+     */
+    private static void addTriad(String[] lemma_1, String[] lemma_2, List<Triad> triads) {
+        Lemma lemma1 = new Lemma();
+        lemma1.setText(lemma_1[0]);
+        lemma1.setPosition(lemma_1[1]);
+        lemma1.setProperty(lemma_1[2]);
+
+        Lemma lemma2 = new Lemma();
+        lemma2.setText(lemma_2[0]);
+        lemma2.setPosition(lemma_2[1]);
+        lemma2.setProperty(lemma_2[2]);
+
+        Triad triad = new Triad();
+        triad.setL_1(lemma1);
+        triad.setL_2(lemma2);
+
+        triads.add(triad);
+
+    }
+
+
+}

+ 493 - 0
algorithm/src/main/java/org/algorithm/core/RuleCheckMachine.java

@@ -0,0 +1,493 @@
+package org.algorithm.core;
+
+import org.algorithm.core.cnn.entity.Lemma;
+import org.algorithm.core.cnn.entity.Triad;
+import org.algorithm.util.MysqlConnector;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.*;
+
+/**
+ * 规则检查机器
+ *
+ * @Author: bijl
+ * @Date: 2019/9/6 10:32
+ * @Description:
+ */
+public class RuleCheckMachine {
+    private final List<FilterRule> filterRules = new ArrayList<>();
+    private Map<String, Map<String, Set<Integer>>> key_1_map = null;
+    private Map<String, Map<String, Set<Integer>>> key_2_map = null;
+    private Map<String, String> punctuations = new HashMap<>();
+    private Map<String, Set<Integer>> despiteMap = null;  // 实体名:[规则uuid列表]
+    private Map<String, Set<Integer>> despiteInsideMap = null; // 实体名:[规则uuid列表]
+    private Map<String, Map<String, Set<Integer>>> insideMap = null;
+
+
+    public RuleCheckMachine() {
+        this.loadRules();
+        this.makeKey1Map();
+        this.makeKey2Map();
+        this.makeInsideMap();
+        this.makeDespiteMap();
+        this.makeDespiteInsideMap();
+    }
+
+
+    /**
+     * 加载规则
+     */
+    public void loadRules() {
+        /**
+         * 连接数据库
+         */
+        String url = "jdbc:mysql://192.168.2.235/test_case?user=root&password=diagbot@20180822";
+        MysqlConnector connector = new MysqlConnector(url);
+        String querySql =
+                "SELECT rr.key_1, rr.type_1, rr.key_2, rr.type_2, rr.inside, rr.inside_type, " +
+                        "rr.despite, rr.despite_inside " +
+                        "FROM relation_neg_rules AS rr " +
+                        "WHERE rr.`status` = 1";
+
+        ResultSet rs = connector.query(querySql);
+        Integer uuid = 0;
+        try {
+            while (rs.next()) {
+                String key_1 = rs.getString("key_1");
+                String type_1 = rs.getString("type_1");
+
+                String key_2 = rs.getString("key_2");
+                String type_2 = rs.getString("type_2");
+
+                String inside = rs.getString("inside");
+                String inside_type = rs.getString("inside_type");
+
+                String despite = rs.getString("despite");
+                String despite_inside = rs.getString("despite_inside");
+
+                String[] despiteSplit = despite.split(",");
+                String[] despiteInsideSplit = despite_inside.split(",");
+                for (int j = 0; j < despiteSplit.length; j++) {
+                    for (int k = 0; k < despiteInsideSplit.length; k++) {
+                        Map<String, String> variableMap = new HashMap<>();
+                        variableMap.put("key_1", key_1);
+                        variableMap.put("type_1", type_1);
+
+                        variableMap.put("key_2", key_2);
+                        variableMap.put("type_2", type_2);
+
+                        variableMap.put("inside", inside);
+                        variableMap.put("inside_type", inside_type);
+
+                        variableMap.put("despite", despiteSplit[j]);
+                        variableMap.put("despite_inside", despiteInsideSplit[k]);
+
+                        FilterRule filterRule = new FilterRule(variableMap);
+                        filterRule.setUuid(uuid);
+                        this.filterRules.add(filterRule);
+
+//                            System.out.println(filterRule);
+
+                        uuid += 1;
+                    }
+                }
+
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+            throw new RuntimeException("加载规则字典失败");
+        } finally {
+            connector.close();
+        }
+    }
+
+    /**
+     * 制作实体1相关信息字典
+     */
+    private void makeKey1Map() {
+        Map<String, Map<String, Set<Integer>>> key_1_map_ = new HashMap<>();
+        Map<String, Set<Integer>> emptyMap = new HashMap<>();
+        Map<String, Set<Integer>> typeMap = new HashMap<>();
+        Map<String, Set<Integer>> wordMap = new HashMap<>();
+        key_1_map_.put("", emptyMap);
+        key_1_map_.put("type", typeMap);
+        key_1_map_.put("word", wordMap);
+
+        for (FilterRule rule : this.filterRules) {
+            String key_1 = rule.getKey_1();
+            String type_1 = rule.getType_1();
+            Integer uuid = rule.getUuid();
+
+            this.inputMaps(key_1, type_1, uuid, emptyMap, typeMap, wordMap, null);
+        }
+        this.key_1_map = key_1_map_;
+    }
+
+
+    /**
+     * 制作实体2相关信息字典
+     */
+    private void makeKey2Map() {
+        Map<String, Map<String, Set<Integer>>> key_2_map_ = new HashMap<>();
+        Map<String, Set<Integer>> emptyMap = new HashMap<>();
+        Map<String, Set<Integer>> typeMap = new HashMap<>();
+        Map<String, Set<Integer>> wordMap = new HashMap<>();
+        key_2_map_.put("", emptyMap);
+        key_2_map_.put("type", typeMap);
+        key_2_map_.put("word", wordMap);
+
+        for (FilterRule rule : this.filterRules) {
+            String key_2 = rule.getKey_2();
+            String type_2 = rule.getType_2();
+            Integer uuid = rule.getUuid();
+
+            this.inputMaps(key_2, type_2, uuid, emptyMap, typeMap, wordMap, null);
+        }
+        this.key_2_map = key_2_map_;
+    }
+
+    /**
+     * 制作内部实体相关信息字典
+     */
+    private void makeInsideMap() {
+        Map<String, Map<String, Set<Integer>>> insideMap_ = new HashMap<>();
+        Map<String, Set<Integer>> punctuationMap = new HashMap<>();
+        Map<String, Set<Integer>> typeMap = new HashMap<>();
+        Map<String, Set<Integer>> typePunctuationMap = new HashMap<>();
+        Map<String, Set<Integer>> wordMap = new HashMap<>();
+        insideMap_.put("punc", punctuationMap);
+        insideMap_.put("type", typeMap);
+        insideMap_.put("typePunctuation", typePunctuationMap);
+        insideMap_.put("word", wordMap);
+
+        for (FilterRule rule : this.filterRules) {
+            String inside = rule.getInside();
+            String insideType = rule.getInsideType();
+            Integer uuid = rule.getUuid();
+            if (insideType.equals("punc"))
+                this.punctuations.put(inside, inside);
+
+            if (",".equals(inside.substring(0, 1)))
+                this.inputMaps(inside, insideType, uuid, null, typePunctuationMap, wordMap, punctuationMap);
+            else
+                this.inputMaps(inside, insideType, uuid, null, typeMap, wordMap, punctuationMap);
+        }
+        this.insideMap = insideMap_;
+    }
+
+    /**
+     * maps输入
+     *
+     * @param key
+     * @param type
+     * @param uuid
+     * @param emptyMap
+     * @param typeMap
+     * @param wordMap
+     */
+    private void inputMaps(String key, String type, Integer uuid, Map<String, Set<Integer>> emptyMap,
+                           Map<String, Set<Integer>> typeMap, Map<String, Set<Integer>> wordMap,
+                           Map<String, Set<Integer>> punctuationMap) {
+
+        if ("".equals(type)) {
+            if (emptyMap.get(key) == null)
+                emptyMap.put(key, new HashSet<>());
+            emptyMap.get(key).add(uuid);
+        } else if ("type".equals(type)) {
+            if (typeMap.get(key) == null)
+                typeMap.put(key, new HashSet<>());
+            typeMap.get(key).add(uuid);
+        } else if ("word".equals(type)) {
+            if (wordMap.get(key) == null)
+                wordMap.put(key, new HashSet<>());
+            wordMap.get(key).add(uuid);
+        } else if ("punc".equals(type)) {
+            if (punctuationMap.get(key) == null)
+                punctuationMap.put(key, new HashSet<>());
+            punctuationMap.get(key).add(uuid);
+        } else {
+            throw new RuntimeException("出现了位置新type");
+        }
+
+    }
+
+
+    /**
+     * 制作例外字典
+     */
+    private void makeDespiteMap() {
+        Map<String, Set<Integer>> despiteMap = new HashMap<>();
+        for (FilterRule rule : this.filterRules) {
+            String despite = rule.getDespite();
+            if (!despite.equals("")) {  // 空白不收录
+                if (despiteMap.get(despite) == null) {
+                    despiteMap.put(despite, new HashSet<>());
+                }
+                despiteMap.get(despite).add(rule.getUuid());  //
+            }
+        }
+        this.despiteMap = despiteMap;
+    }
+
+
+    /**
+     * 制作例外_内部字典
+     */
+    private void makeDespiteInsideMap() {
+        Map<String, Set<Integer>> despiteInsideMap = new HashMap<>();
+        for (FilterRule rule : this.filterRules) {
+            String despiteInside = rule.getDespiteInside();
+            if (!despiteInside.equals("")) {  // 空白不收录
+                if (despiteInsideMap.get(despiteInside) == null) {
+                    despiteInsideMap.put(despiteInside, new HashSet<>());
+                }
+                despiteInsideMap.get(despiteInside).add(rule.getUuid());  //
+            }
+        }
+        this.despiteInsideMap = despiteInsideMap;
+    }
+
+    /**
+     * 名称—类别—开始位置类
+     */
+    class NameTypeStartPosition implements Comparable<NameTypeStartPosition> {
+        private String name;
+        private String type;
+        private int startPosition;
+
+        public NameTypeStartPosition(String name, String type, int startPosition) {
+            this.name = name;
+            this.type = type;
+            this.startPosition = startPosition;
+        }
+
+        @Override
+        public int compareTo(NameTypeStartPosition o) {
+            return this.startPosition - o.getStartPosition();
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public String getType() {
+            return type;
+        }
+
+        public void setType(String type) {
+            this.type = type;
+        }
+
+        public int getStartPosition() {
+            return startPosition;
+        }
+
+        public void setStartPosition(int startPosition) {
+            this.startPosition = startPosition;
+        }
+
+        @Override
+        public String toString() {
+            return "NameTypeStartPosition{" +
+                    "name='" + name + '\'' +
+                    ", type='" + type + '\'' +
+                    ", startPosition=" + startPosition +
+                    '}';
+        }
+
+    }
+
+    /**
+     * 获取已排序的(名称,类别,开始位置)对象
+     *
+     * @param triads
+     * @return
+     */
+    public List<NameTypeStartPosition> getSortedNameTypeByPosition(List<Triad> triads) {
+        List<NameTypeStartPosition> nameTypeStartPositions = new ArrayList<>();
+        for (Triad triad : triads) {
+            Lemma l1 = triad.getL_1();
+            Lemma l2 = triad.getL_2();
+            nameTypeStartPositions.add(
+                    new NameTypeStartPosition(l1.getText(), l1.getProperty(), l1.getStartPosition()));
+            nameTypeStartPositions.add(
+                    new NameTypeStartPosition(l2.getText(), l2.getProperty(), l2.getStartPosition()));
+        }
+        nameTypeStartPositions.sort(Comparator.naturalOrder());
+
+        return nameTypeStartPositions;
+    }
+
+    /**
+     * 是否移除
+     *
+     * @param nameTypeStartPositions
+     * @param startIndex
+     * @param endIndex
+     * @return
+     */
+    public boolean isRemove(List<NameTypeStartPosition> nameTypeStartPositions, int startIndex, int endIndex,
+                            String sentence) {
+        Set<Integer> remainUuids = new HashSet<>();  // 剩余规则的uuid
+        for (FilterRule rule : this.filterRules)
+            remainUuids.add(rule.getUuid());
+
+        // 过滤实体名称触发例外条件情况
+        String entity_1_name = nameTypeStartPositions.get(startIndex).getName();
+        String entity_1_type = nameTypeStartPositions.get(startIndex).getType();
+
+        String entity_2_name = nameTypeStartPositions.get(endIndex).getType();
+        String entity_2_type = nameTypeStartPositions.get(endIndex).getType();
+
+        Set<Integer> set = null;
+        set = this.despiteMap.get(entity_1_name);  // 过滤有实体1名为例外情况(即,不成立)的规则(的uuid)
+        this.removeAll(remainUuids, set);
+
+        set = this.despiteMap.get(entity_2_name);  // 过滤有实体2名为例外情况(即,不成立)的规则(的uuid)
+        this.removeAll(remainUuids, set);
+
+        // 过滤中间实体的名称触发例外条件情况
+        for (int i = startIndex; i <= endIndex; i++) {
+            NameTypeStartPosition nameTypeStartPosition = nameTypeStartPositions.get(i);
+            set = this.despiteInsideMap.get(nameTypeStartPosition.getName());
+            this.removeAll(remainUuids, set);
+        }
+
+        // 三板斧过滤
+        // 实体1,过滤
+        set = new HashSet<>();
+        this.addAll(set, this.key_1_map.get("").get(""));
+        // 满足,形如("形容词", "type") 过滤条件的规则
+        this.addAll(set, this.key_1_map.get("type").get(entity_1_type));
+        // 满足,形如("胸痛", "word") 过滤条件的规则
+        this.addAll(set, this.key_1_map.get("word").get(entity_1_name));
+        this.retainAll(remainUuids, set);  // 求交集,同事满足实体1相关的过滤条件,且不不满足例外情况
+        if (remainUuids.size() == 0)
+            return false;
+
+        // 实体2,过滤
+        set = new HashSet<>();
+        this.addAll(set, this.key_2_map.get("").get(""));
+        // 满足,形如("形容词", "type") 过滤条件的规则
+        this.addAll(set, this.key_2_map.get("type").get(entity_2_type));
+        // 满足,形如("胸痛", "word") 过滤条件的规则
+        this.addAll(set, this.key_2_map.get("word").get(entity_2_name));
+        this.retainAll(remainUuids, set);  // 求交集,同事满足实体1相关的过滤条件,且不不满足例外情况
+        if (remainUuids.size() == 0)
+            return false;
+
+        // 中间实体过滤
+        set = new HashSet<>();
+        for (int i = startIndex; i <= endIndex; i++) {
+            NameTypeStartPosition nameTypeStartPosition = nameTypeStartPositions.get(i);
+            // 中间实体满足,形如("胸痛", "word") 过滤条件的规则
+            this.addAll(set, this.insideMap.get("word").get(nameTypeStartPosition.getName()));
+            // 中间实体满足,形如(";", "punc") 过滤条件的规则
+            this.addAll(set, this.insideMap.get("type").get(nameTypeStartPosition.getType()));  // 没有逗号的
+        }
+
+        int entity_1_start = nameTypeStartPositions.get(startIndex).getStartPosition();
+        int entity_2_start = nameTypeStartPositions.get(endIndex).getStartPosition();
+
+        // 标点过滤
+        String aPunc = null;
+        for (int i=entity_1_start; i<entity_2_start;i++){
+            aPunc = sentence.substring(i, i+1);
+            if (this.punctuations.get(aPunc) != null)
+                this.addAll(set, this.insideMap.get("punc").get(aPunc));
+        }
+
+        // 中文和英文逗号+属性 过滤
+        String[] commas = {",", ","};
+        int commaIndex = 0;
+        String commaPadType = null;  // 逗号拼接上类型
+        for (String comma: commas) {
+            commaIndex = sentence.indexOf(comma, entity_1_start + 1);  // 逗号位置
+            while (commaIndex > -1 && commaIndex < entity_2_start) {
+                commaIndex = sentence.indexOf(comma, commaIndex + 1);  // 下一个逗号
+                for (int i = startIndex; i <= endIndex; i++) {  // 每个逗号与后面的所有实体都匹配一次
+                    NameTypeStartPosition nameTypeStartPosition = nameTypeStartPositions.get(i);
+                    if (nameTypeStartPosition.getStartPosition() > commaIndex) {
+                        commaPadType = "," + nameTypeStartPosition.getType();
+                        this.addAll(set, this.insideMap.get("typePunctuation").get(commaPadType));
+                    }
+
+                }
+            }
+
+        }
+
+        this.retainAll(remainUuids, set);  // 求交集,同事中间实体相关的过滤条件,且不不满足例外情况
+
+//        for (FilterRule rule: this.filterRules) {
+//            if (remainUuids.contains(rule.getUuid()))
+//                System.out.println(rule);
+//
+//        }
+
+        return remainUuids.size() > 0;  // 还有规则满足,则过滤
+
+    }
+
+    /**
+     * 求差集,避免null和空集
+     *
+     * @param basicSet
+     * @param set
+     */
+    private void removeAll(Set<Integer> basicSet, Set<Integer> set) {
+        if (set != null && set.size() > 0)
+            basicSet.removeAll(set);
+    }
+
+    /**
+     * 求交集,避免null和空集
+     *
+     * @param basicSet
+     * @param set
+     */
+    private void addAll(Set<Integer> basicSet, Set<Integer> set) {
+        if (set != null && set.size() > 0)
+            basicSet.addAll(set);
+    }
+
+    /**
+     * 求并集,避免null和空集
+     *
+     * @param basicSet
+     * @param set
+     */
+    private void retainAll(Set<Integer> basicSet, Set<Integer> set) {
+        if (set != null && set.size() > 0)
+            basicSet.retainAll(set);
+    }
+
+    /**
+     * 检查并移除
+     *
+     * @param sentence 句子
+     * @param triads 三元组列表
+     */
+    public void checkAndRemove(String sentence, List<Triad> triads) {
+        List<NameTypeStartPosition> nameTypeStartPositions = this.getSortedNameTypeByPosition(triads);
+        Map<Integer, Integer> startPositionToIndexMap = new HashMap<>();
+        for (int i = 0; i < nameTypeStartPositions.size(); i++)
+            startPositionToIndexMap.put(nameTypeStartPositions.get(i).getStartPosition(), i);
+
+        Iterator<Triad> it = triads.iterator();
+        while (it.hasNext()) {  // 遍历三元组,移除满足过滤规则的
+            Triad triad = it.next();
+            int startIndex = startPositionToIndexMap.get(triad.getL_1().getStartPosition());
+            int endIndex = startPositionToIndexMap.get(triad.getL_2().getStartPosition());
+            if (isRemove(nameTypeStartPositions, startIndex, endIndex, sentence)) {
+                it.remove();
+            }
+        }
+    }
+}

+ 3 - 4
algorithm/src/main/java/org/algorithm/core/cnn/AlgorithmCNNExecutor.java

@@ -1,13 +1,12 @@
 package org.algorithm.core.cnn;
 
-import org.algorithm.core.cnn.entity.Lemma;
 import org.algorithm.core.cnn.entity.Triad;
 
 import java.util.List;
 
 /**
  * @ClassName org.algorithm.core.cnn.model.AlgorithmCNNExecutor
- * @Description TODO
+ * @Description
  * @Author fyeman
  * @Date 2019/1/17/017 19:18
  * @Version 1.0
@@ -16,8 +15,8 @@ public abstract class AlgorithmCNNExecutor {
     /**
      *
      * @param content 输入句子
-     * @param triads 实体列表
-     * @return
+     * @param triads 实体列表(三元组列表)
+     * @return  [[有关系的一系列词]]
      */
     public abstract List<Triad> execute(String content, List<Triad> triads);
 }

+ 22 - 0
algorithm/src/main/java/org/algorithm/core/cnn/AlgorithmCNNExecutorPacs.java

@@ -0,0 +1,22 @@
+package org.algorithm.core.cnn;
+
+import org.algorithm.core.cnn.entity.Triad;
+
+import java.util.List;
+
+/**
+ * @ClassName org.algorithm.core.cnn.model.AlgorithmCNNExecutor
+ * @Description
+ * @Author fyeman
+ * @Date 2019/1/17/017 19:18
+ * @Version 1.0
+ **/
+public abstract class AlgorithmCNNExecutorPacs {
+    /**
+     *
+     * @param content 输入句子
+     * @param triads 实体列表(三元组列表)
+     * @return  [[有关系的一系列词]]
+     */
+    public abstract List<List<String>>  execute(String content, List<Triad> triads);
+}

+ 1 - 1
algorithm/src/main/java/org/algorithm/core/cnn/dataset/RelationExtractionDataSet.java

@@ -17,7 +17,7 @@ import com.alibaba.fastjson.JSONObject;
 public class RelationExtractionDataSet {
 
     private Map<String, Integer> char2id = new HashMap<>();
-    public final int MAX_LEN = 512;
+    public final int MAX_LEN = 256;
 
 
     public RelationExtractionDataSet(String dir) {

+ 32 - 1
algorithm/src/main/java/org/algorithm/core/cnn/entity/Lemma.java

@@ -10,12 +10,38 @@ import java.util.List;
  * @Date 2019/1/17/017 19:15
  * @Version 1.0
  **/
-public class Lemma {
+public class Lemma implements Comparable<Lemma> {
     private String text;
     private String position;
     private int len;
     private String property;
 
+    private Lemma parent;
+
+    private boolean haveChildren = false;
+
+    public boolean isHaveChildren() {
+        return haveChildren;
+    }
+
+    public void setHaveChildren(boolean haveChildren) {
+        this.haveChildren = haveChildren;
+    }
+
+    public Lemma getParent() {
+        return parent;
+    }
+
+    public void setParent(Lemma parent) {
+        this.parent = parent;
+    }
+
+    public int getStartPosition() {
+        String[] pos = this.position.split(",");
+        return Integer.parseInt(pos[0]);
+    }
+
+
     private List<Lemma> relationLemmas = new ArrayList<>();
 
     public String getText() {
@@ -64,4 +90,9 @@ public class Lemma {
         }
         relationLemmas.add(l);
     }
+
+    @Override
+    public int compareTo(Lemma o) {
+        return this.getStartPosition() - o.getStartPosition();
+    }
 }

+ 40 - 13
algorithm/src/main/java/org/algorithm/core/cnn/model/RelationExtractionEnsembleModel.java

@@ -1,6 +1,8 @@
 package org.algorithm.core.cnn.model;
 
-import org.algorithm.core.cnn.AlgorithmCNNExecutor;
+import org.algorithm.core.RelationTreeUtils;
+import org.algorithm.core.RuleCheckMachine;
+import org.algorithm.core.cnn.AlgorithmCNNExecutorPacs;
 import org.algorithm.core.cnn.dataset.RelationExtractionDataSet;
 import org.algorithm.core.cnn.entity.Triad;
 import org.diagbot.pub.utils.PropertiesUtil;
@@ -21,7 +23,7 @@ import java.util.concurrent.*;
  * @Date: 2019/1/22 10:21
  * @Description: 集成模型
  */
-public class RelationExtractionEnsembleModel extends AlgorithmCNNExecutor {
+public class RelationExtractionEnsembleModel extends AlgorithmCNNExecutorPacs {
     private final String X_PLACEHOLDER = "X";
     private final String PREDICTION = "prediction/prediction";
     private final int NUM_LABEL = 1;
@@ -30,8 +32,10 @@ public class RelationExtractionEnsembleModel extends AlgorithmCNNExecutor {
     private RelationExtractionDataSet dataSet;
     private RelationExtractionSubModel[] subModels = new RelationExtractionSubModel[2];
     private ExecutorService executorService = Executors.newCachedThreadPool();
+    private final RuleCheckMachine ruleCheckMachine = new RuleCheckMachine();
 
     public RelationExtractionEnsembleModel() {
+        // 解析路径
         PropertiesUtil prop = new PropertiesUtil("/algorithm.properties");
 
         String modelsPath = prop.getProperty("basicPath");  // 模型基本路径
@@ -39,18 +43,20 @@ public class RelationExtractionEnsembleModel extends AlgorithmCNNExecutor {
         dataSetPath = dataSetPath + File.separator + "char2id.json";
         String exportDir = modelsPath.replace("model_version_replacement", "ensemble_model_2");
 
+        // 加载数据集和初始化集成模型
         this.dataSet = new RelationExtractionDataSet(dataSetPath);
         this.init(exportDir);
 
+        // 添加子模型系数,并加载子模型cnn_1d_low
         Map<String, Tensor<Float>> cnn_1d_low_map = new HashMap<>();
-        cnn_1d_low_map.put("keep_prob",Tensor.create(1.0f, Float.class));
+        cnn_1d_low_map.put("keep_prob", Tensor.create(1.0f, Float.class));
         subModels[0] = new RelationExtractionSubModel("cnn_1d_low", cnn_1d_low_map);
-//        subModels[1] = new RelationExtractionSubModel("cnn_1d_lstm_low");
 
+        // 添加子模型系数,并加载子模型lstm_low_api
         Map<String, Tensor<Float>> lstm_low_api_map = new HashMap<>();
-        lstm_low_api_map.put("input_keep_prob",Tensor.create(1.0f, Float.class));
-        lstm_low_api_map.put("output_keep_prob",Tensor.create(1.0f, Float.class));
-        lstm_low_api_map.put("state_keep_prob",Tensor.create(1.0f, Float.class));
+        lstm_low_api_map.put("input_keep_prob", Tensor.create(1.0f, Float.class));
+        lstm_low_api_map.put("output_keep_prob", Tensor.create(1.0f, Float.class));
+        lstm_low_api_map.put("state_keep_prob", Tensor.create(1.0f, Float.class));
         subModels[1] = new RelationExtractionSubModel("lstm_low_api", lstm_low_api_map);
     }
 
@@ -92,12 +98,24 @@ public class RelationExtractionEnsembleModel extends AlgorithmCNNExecutor {
         return inputValues;
     }
 
+
+    /**
+     * 数据预处理,包括过滤,等操作
+     * @param content
+     * @param triads
+     */
+    private void preProcess(String content, List<Triad> triads){
+        if (!(content.length() > this.dataSet.MAX_LEN) && triads.size() > 0) // 句子长度不超过MAX_LEN,有三元组
+            this.ruleCheckMachine.checkAndRemove(content, triads);
+    }
+
     @Override
-    public List<Triad> execute(String content, List<Triad> triads) {
-        // 句子长度不超过MAX_LEN,有三元组
-        if (content.length() > this.dataSet.MAX_LEN || triads.size() < 1) {
-            return new ArrayList<>();
-        }
+    public List<List<String>> execute(String content, List<Triad> triads) {
+        // 预处理
+        this.preProcess(content, triads);
+        if (content.length() > this.dataSet.MAX_LEN || triads.size() < 1)  // 句子长度不超过MAX_LEN,有三元组
+            return null;
+
         int[][] inputValues = this.convertData(content, triads);  // shape = [3, batchSize * this.subModels.length]
         int batchSize = triads.size();
 
@@ -159,7 +177,16 @@ public class RelationExtractionEnsembleModel extends AlgorithmCNNExecutor {
         for (Triad triad : deleteTriads)
             triads.remove(triad);
 
-        return triads;
+        return this.triadsToRelationTreeBranches(triads);
+    }
+
+    /**
+     * 从三元组列表到关系树分枝
+     * @param triads
+     * @return
+     */
+    public List<List<String>> triadsToRelationTreeBranches(List<Triad> triads) {
+        return RelationTreeUtils.triadsToRelationTreeBranches(triads);
     }
 
 

+ 4 - 4
algorithm/src/main/java/org/algorithm/core/cnn/model/RelationExtractionModel.java

@@ -4,7 +4,7 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
-import org.algorithm.core.cnn.AlgorithmCNNExecutor;
+import org.algorithm.core.cnn.AlgorithmCNNExecutorPacs;
 import org.algorithm.core.cnn.dataset.RelationExtractionDataSet;
 import org.algorithm.core.cnn.entity.LemmaInfo;
 import org.algorithm.core.cnn.entity.Triad;
@@ -21,7 +21,7 @@ import java.util.List;
  * @Date: 2019/1/22 10:21
  * @Decription:
  */
-public class RelationExtractionModel extends AlgorithmCNNExecutor {
+public class RelationExtractionModel extends AlgorithmCNNExecutorPacs {
 //    self.X = tf.placeholder(tf.int32, shape=[None, self.max_length], name='X')
 //    self.pos1 = tf.placeholder(tf.int32, shape=[None, self.max_length], name='pos1')
 //    self.pos2 = tf.placeholder(tf.int32, shape=[None, self.max_length], name='pos2')
@@ -54,7 +54,7 @@ public class RelationExtractionModel extends AlgorithmCNNExecutor {
     }
 
     @Override
-    public List<Triad> execute(String content, List<Triad> triads) {
+    public List<List<String>> execute(String content, List<Triad> triads) {
 //        List<Lemma[]> combinations = new ArrayList<>();
 //        // 组合
 //        for(int i=0; i < lemmas.size() - 1; i++){  // 两两组合成实体对
@@ -83,7 +83,7 @@ public class RelationExtractionModel extends AlgorithmCNNExecutor {
 //            }
 //
 //        }
-        return triads;
+        return null;
     }
 
     /**

+ 2 - 1
algorithm/src/main/java/org/algorithm/core/neural/DiagnosisPredictExecutor.java

@@ -15,7 +15,8 @@ public class DiagnosisPredictExecutor extends AlgorithmNeuralExecutor {
     public DiagnosisPredictExecutor() {
         String modelVersion = "diagnosisPredict.version";
 
-        this.model = TensorFlowModelLoadFactory.create(modelVersion);
+//        this.model = TensorFlowModelLoadFactory.create(modelVersion);
+        this.model = TensorFlowModelLoadFactory.createAndFilterDiagnosis(modelVersion);  // 加了疾病过滤
     }
 
 }

+ 30 - 7
algorithm/src/main/java/org/algorithm/core/neural/TensorFlowModelLoadFactory.java

@@ -11,13 +11,10 @@ import org.diagbot.pub.utils.PropertiesUtil;
  * @Description:
  */
 public class TensorFlowModelLoadFactory {
-    
+
     /**
      * 加载并创建模型类
-     * @param exportDir  模型保存地址
-     * @param inputOpName  输入op的名称
-     * @param outputOpName  输出op的名称
-     * @param dataSet     模型使用的数据集
+     * @param modelVersion  模型版本号
      * @return 模型
      */
     public static TensorflowModel create(String modelVersion) {
@@ -28,10 +25,9 @@ public class TensorFlowModelLoadFactory {
         String inputOpName = "X";  // 统一输入op名称
         String outputOpName = "softmax/softmax";  // 统一输出op名称
         
-        // TODO:修改的地方
 //        NNDataSet dataSet = new NNDataSetImplNonParallel(modelVersion);  // 新模型
         NNDataSet dataSet = new NNDataSetImpl(modelVersion);  // 老模型
-        
+
         String modelPath =prop.getProperty("basicPath");  // 模型基本路径
         modelVersion = prop.getProperty(modelVersion);
         modelPath = modelPath.replace("model_version_replacement", modelVersion);  // 生成模型路径
@@ -41,4 +37,31 @@ public class TensorFlowModelLoadFactory {
         return tm;
     }
 
+    /**
+     * 加载并创建模型类
+     * @param modelVersion  模型版本号
+     * @return 模型
+     */
+    public static TensorflowModel createAndFilterDiagnosis(String modelVersion) {
+
+
+        PropertiesUtil prop = new PropertiesUtil("/algorithm.properties");
+
+        String inputOpName = "X";  // 统一输入op名称
+        String outputOpName = "softmax/softmax";  // 统一输出op名称
+
+        NNDataSet dataSet = new NNDataSetImpl(modelVersion);  // 老模型
+
+        dataSet.setDoFilterDiagnosis(true);
+        dataSet.readFilterDiagnosisDict();
+
+        String modelPath =prop.getProperty("basicPath");  // 模型基本路径
+        modelVersion = prop.getProperty(modelVersion);
+        modelPath = modelPath.replace("model_version_replacement", modelVersion);  // 生成模型路径
+
+        TensorflowModel tm = new TensorflowModel(modelPath, inputOpName, outputOpName,
+                dataSet);
+        return tm;
+    }
+
 }

+ 122 - 13
algorithm/src/main/java/org/algorithm/core/neural/dataset/NNDataSet.java

@@ -1,10 +1,10 @@
 package org.algorithm.core.neural.dataset;
 
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 
 /**
  * 神经网络用数据处理模块
+ *
  * @Author: bijl
  * @Date: 2018年7月20日-下午4:01:34
  * @Description:
@@ -13,17 +13,20 @@ public abstract class NNDataSet {
     protected final int NUM_FEATURE;
     private final int NUM_LABEL;
     protected final Map<String, Integer> FEATURE_DICT = new HashMap<>();
-    
+
     // 新版本新加的三种关键词
     protected final Map<String, Integer> PARTBODY_DICT = new HashMap<>();
     protected final Map<String, Integer> PROPERTY_DICT = new HashMap<>();
     protected final Map<String, Integer> DURATION_DICT = new HashMap<>();
-    
+
     protected final Map<String, Integer> LABEL_DICT = new HashMap<>();
     protected final Map<String, Integer> NEGATIVE_DICT = new HashMap<>();
+    protected final Map<String, String> RE_SPLIT_WORD_DICT = new HashMap<>();
+    protected final Map<String, Map<String, Integer>> RELATED_DIAGNOSIS_DICT = new HashMap<>();
+    protected final List<String> FEATURE_NAME_STORE = new ArrayList<>();
     private final String[] FEATURE_DICT_ARRAY;
     private final String[] LABEL_DICT_ARRAY;
-
+    private boolean doFilterDiagnosis = false;
 
     public NNDataSet(String modelAndVersion) {
         this.readDict(modelAndVersion);
@@ -32,10 +35,12 @@ public abstract class NNDataSet {
         this.FEATURE_DICT_ARRAY = new String[this.NUM_FEATURE];
         this.LABEL_DICT_ARRAY = new String[this.NUM_LABEL];
         this.makeDictArr();
+        this.readReSplitWordDict();
     }
-    
+
     /**
      * 装外部输入转为特征向量
+     *
      * @param inputs
      * @return
      */
@@ -45,28 +50,118 @@ public abstract class NNDataSet {
      * 读取特征和类别字典
      */
     public abstract void readDict(String modelAndVersion);
-    
+
+    /**
+     * 读取再分词字典
+     */
+    public abstract void readReSplitWordDict();
+
+    /**
+     * 读取过滤字典
+     */
+    public abstract void readFilterDiagnosisDict();
+
     /**
      * 生成字典列表
      */
     private void makeDictArr() {
-        for (Map.Entry<String, Integer> entry : this.FEATURE_DICT.entrySet()) 
+        for (Map.Entry<String, Integer> entry : this.FEATURE_DICT.entrySet())
             this.FEATURE_DICT_ARRAY[entry.getValue()] = entry.getKey();
-        
-        for (Map.Entry<String, Integer> entry : this.LABEL_DICT.entrySet()) 
+
+        for (Map.Entry<String, Integer> entry : this.LABEL_DICT.entrySet())
             this.LABEL_DICT_ARRAY[entry.getValue()] = entry.getKey();
-        
+
+    }
+
+    /**
+     * 打包特征名和概率 + 过滤疾病
+     * 基本操作,过滤前20个疾病,如果
+     *
+     * @param predict 模型输出
+     * @return
+     */
+    public Map<String, Float> wrapAndFilter(float[][] predict) {
+        List<NameAndValue> nameAndValueList = new ArrayList<>();
+        for (int i = 0; i < predict[0].length; i++)
+            nameAndValueList.add(new NameAndValue(this.LABEL_DICT_ARRAY[i], predict[0][i]));
+        nameAndValueList.sort(Comparator.reverseOrder());  // 按概率从大到小排列
+
+        Map<String, Float> result = new HashMap<>();
+        Integer cnt = 0;
+        String diagnosis;
+        NameAndValue nameAndValue;
+        Map<String, Integer> relatedDiagnoses = null;
+        for (int i = 0; i < nameAndValueList.size(); i++) {
+            nameAndValue = nameAndValueList.get(i);
+            diagnosis = nameAndValue.getName();
+            for (String featureName : this.FEATURE_NAME_STORE) {
+                relatedDiagnoses = this.RELATED_DIAGNOSIS_DICT.get(featureName);
+                if (relatedDiagnoses != null && relatedDiagnoses.get(diagnosis) != null) {
+                    result.put(nameAndValue.getName(), nameAndValue.getValue());
+                    cnt += 1;
+                }
+            }
+            if ((i >= 20 || i >= 50) && cnt > 0)  // 如果前20或50个推送中有相关的疾病,只过滤他们
+                break;
+        }
+        return result;
+    }
+
+    /**
+     * 用于排序的类
+     */
+    class NameAndValue implements Comparable<NameAndValue> {
+
+        private String name;
+        private Float value;
+
+        NameAndValue(String name, Float value) {
+            this.name = name;
+            this.value = value;
+        }
+
+        @Override
+        public int compareTo(NameAndValue o) {
+            if (this.value > o.getValue())
+                return 1;
+            else if (this.value.equals(o.getValue()))
+                return 0;
+            else
+                return -1;
+        }
+
+        public Float getValue() {
+            return value;
+        }
+
+        public String getName() {
+            return name;
+        }
     }
 
     /**
      * 打包模型输出结果给调用者
-     * 
+     *
      * @param predict 模型输出
      * @return
      */
     public Map<String, Float> wrap(float[][] predict) {
+        if (this.doFilterDiagnosis)  // 过滤疾病
+            return this.wrapAndFilter(predict);
+        else
+            return this.basicWrap(predict);
+    }
+
+
+    /**
+     * 打包模型输出结果给调用者
+     *
+     * @param predict 模型输出
+     * @return
+     */
+    public Map<String, Float> basicWrap(float[][] predict) {
         Map<String, Float> result = new HashMap<>();
-        for (int i=0; i<predict[0].length; i++) {  // 只返回一维向量
+        for (int i = 0; i < predict[0].length; i++) {  // 只返回一维向量
             result.put(this.LABEL_DICT_ARRAY[i], predict[0][i]);
         }
         return result;
@@ -79,6 +174,15 @@ public abstract class NNDataSet {
         return this.NUM_FEATURE;
     }
 
+    /**
+     *  存储特征名称
+     * @param features
+     */
+    public void storeFeatureNames(Map<String, Map<String, String>> features){
+        this.FEATURE_NAME_STORE.clear();
+        this.FEATURE_NAME_STORE.addAll(features.keySet());
+    }
+
     /**
      * @return
      */
@@ -86,4 +190,9 @@ public abstract class NNDataSet {
         return this.NUM_LABEL;
     }
 
+
+    public void setDoFilterDiagnosis(boolean doFilterDiagnosis) {
+        this.doFilterDiagnosis = doFilterDiagnosis;
+    }
+
 }

+ 113 - 73
algorithm/src/main/java/org/algorithm/core/neural/dataset/NNDataSetImpl.java

@@ -3,6 +3,7 @@ package org.algorithm.core.neural.dataset;
 import org.algorithm.util.TextFileReader;
 import org.diagbot.pub.utils.PropertiesUtil;
 
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -10,7 +11,7 @@ import java.util.Map.Entry;
 
 /**
  * 门诊诊断推送用数据集
- * 
+ *
  * @Author: bijl
  * @Date: 2018年7月26日-上午10:19:43
  * @Description:
@@ -22,9 +23,13 @@ public class NNDataSetImpl extends NNDataSet {
         super(modelAndVersion);
     }
 
-
     @Override
     public float[] toFeatureVector(Map<String, Map<String, String>> inputs) {
+
+        // 新添加的操作
+        this.reSplitWord(inputs);  // 再分词
+        this.storeFeatureNames(inputs);  // 保存特征名称
+
         float[] featureVector = new float[this.NUM_FEATURE];
 
         Iterator<Entry<String, Map<String, String>>> entries = inputs.entrySet().iterator();
@@ -32,13 +37,9 @@ public class NNDataSetImpl extends NNDataSet {
         String featureName = "";
         Integer position = -1;
         Integer negative = 0;
-        // Integer partbodyValue = 0;
         float positive_value = 1.0f;
         float negative_value = -1.0f;
         Map<String, String> featureValues = null;
-        // String partbody = null;
-        // String[] partbodys = null;
-        // String sn = null;
 
         /**
          * 数据方案设计
@@ -51,11 +52,6 @@ public class NNDataSetImpl extends NNDataSet {
             featureValues = entry.getValue();
             position = this.FEATURE_DICT.get(featureName);
             negative = NEGATIVE_DICT.get(featureValues.get("negative"));
-            // 突出主症状的数据方案
-            // sn = featureValues.get("sn");
-            // if("0".equals(sn)) {
-            // negative = negative * 10;
-            // }
 
             if (position != null)
                 if (negative == 1)
@@ -65,91 +61,36 @@ public class NNDataSetImpl extends NNDataSet {
                 else
                     System.out.println("New Nagetive! This may lead to an error.");
 
-
-
-            /**
-             * 部位附属症状数据表示方案 partbodyValue = this.PARTBODY_DICT.get(featureValues.get("partbody"));
-             * if(partbodyValue != null) { value = 1.0f * partbodyValue /
-             * this.PARTBODY_DICT.get("NULL"); // 部位值表示 value = (float)(Math.round(value *
-             * 100000))/100000; // 保留5位有效数字 } value = negative * value; featureVector[position] =
-             * value;
-             * 
-             */
-
         }
 
         return featureVector;
     }
 
-
-    /**
-     * 读取字典
-     */
-//     @Override
-//     public void readDict(String modelAndVersion) {
-//    
-//     PropertiesUtil prop = new PropertiesUtil("/algorithm.properties");
-//     String model_version = prop.getProperty(modelAndVersion);
-//     model_version = model_version.trim();
-//    
-//     String url = "jdbc:mysql://192.168.2.235/diagbot-app?user=root&password=diagbot@20180822";
-//     MysqlConnector connector = new MysqlConnector(url);
-//     String querySql = "SELECT md._name, md._index, md.type_id " + "FROM model_dictionary AS md "
-//     + "WHERE md.belong_model = 'outpatient_model'";
-//    
-//     querySql = querySql.replace("outpatient_model", model_version);
-//     ResultSet rs = connector.query(querySql);
-//     try {
-//     while (rs.next()) {
-//     int type_id = rs.getInt("type_id");
-//     int _index = rs.getInt("_index");
-//     String _name = rs.getString("_name");
-//    
-//     if (type_id == 1)
-//     this.FEATURE_DICT.put(_name, _index);
-//     else if (type_id == 2)
-//     this.LABEL_DICT.put(_name, _index);
-//     else if (type_id == 8)
-//     this.NEGATIVE_DICT.put(_name, _index);
-//    
-//     }
-//    
-//     System.out.println("feature size:"+this.FEATURE_DICT.size());
-//    
-//     } catch (SQLException e) {
-//     e.printStackTrace();
-//     throw new RuntimeException("加载特征和类别字典失败");
-//     } finally {
-//     connector.close();
-//     }
-//    
-//     }
-
     @Override
     public void readDict(String modelAndVersion) {
-        
+
         PropertiesUtil prop = new PropertiesUtil("/algorithm.properties");
         String model_version = prop.getProperty(modelAndVersion);
 
         String filePath = prop.getProperty("basicPath");  // 基本目录
         filePath = filePath.substring(0, filePath.indexOf("model_version_replacement"));
-        
+
         filePath = filePath + "dictionaries.bin";  // 字典文件位置
-        
+
         List<String> lines = TextFileReader.readLines(filePath);
 
         boolean firstLine = true;
-        
+
         String[] temp = null;
         for (String line : lines) {
             if (firstLine) {  // 去除第一行
                 firstLine = false;
                 continue;
             }
-            
+
             temp = line.split("\\|");
-            
-            if(temp[3].equals(model_version)){
+
+            if (temp[3].equals(model_version)) {
                 int type_id = Integer.parseInt(temp[2]);
                 int _index = Integer.parseInt(temp[1]);
                 String _name = temp[0];
@@ -168,4 +109,103 @@ public class NNDataSetImpl extends NNDataSet {
 
     }
 
+    /**
+     * 再分词:
+     * 基本操作:
+     * 如果再分词表中有某一词项,则移除它,并添加该此项对应的细分词项
+     *
+     * @param inputs 输入
+     */
+    public void reSplitWord(Map<String, Map<String, String>> inputs) {
+        Iterator<Entry<String, Map<String, String>>> entries = inputs.entrySet().iterator();
+
+        String featureName = "";
+        String[] splitWords = null;
+        Map<String, String> featureValues = null;
+        Entry<String, Map<String, String>> entry;
+
+        Map<String, Map<String, String>> tempHashMap = new HashMap<>();  // 用于暂存key, value
+
+        while (entries.hasNext()) {
+            entry = entries.next();
+            featureName = entry.getKey();
+            if (this.FEATURE_DICT.get(featureName) == null  // 特征字典中没有然后再分词
+                    && this.RE_SPLIT_WORD_DICT.get(featureName) != null) {
+                entries.remove();  // 移除该词项
+                splitWords = this.RE_SPLIT_WORD_DICT.get(featureName).split(",");
+                for (String word : splitWords) {  // 添加细分词项
+                    featureValues = new HashMap<>();
+                    featureValues.put("negative", "有"); // 设置为阳性词
+                    tempHashMap.put(word, featureValues);
+                }
+
+            }
+        }
+
+        inputs.putAll(tempHashMap);
+    }
+
+    @Override
+    public void readReSplitWordDict() {
+        PropertiesUtil prop = new PropertiesUtil("/algorithm.properties");
+        String filePath = prop.getProperty("basicPath");  // 基本目录
+        filePath = filePath.substring(0, filePath.indexOf("model_version_replacement"));
+
+        filePath = filePath + "re_split_word.bin";  // 字典文件位置
+
+        List<String> lines = TextFileReader.readLines(filePath);
+
+        boolean firstLine = true;
+
+        String[] temp = null;
+        Map<String, String> feature_map = null;
+        for (String line : lines) {
+            if (firstLine) {  // 去除第一行
+                firstLine = false;
+                continue;
+            }
+
+            temp = line.split("\\|");
+
+            this.RE_SPLIT_WORD_DICT.put(temp[0], temp[1]);
+
+        }
+
+        System.out.println("再分词,词条数:" + this.RE_SPLIT_WORD_DICT.size());
+
+    }
+
+    @Override
+    public void readFilterDiagnosisDict() {
+        PropertiesUtil prop = new PropertiesUtil("/algorithm.properties");
+        String filePath = prop.getProperty("basicPath");  // 基本目录
+        filePath = filePath.substring(0, filePath.indexOf("model_version_replacement"));
+
+        filePath = filePath + "filter_diagnoses.bin";  // 字典文件位置
+
+        List<String> lines = TextFileReader.readLines(filePath);
+
+        boolean firstLine = true;
+
+        String[] temp = null;
+        String[] diagnoses = null;
+        Map<String, Integer> diagnosis_map = null;
+        for (String line : lines) {
+            if (firstLine) {  // 去除第一行
+                firstLine = false;
+                continue;
+            }
+
+            temp = line.split("\\|");
+            diagnoses = temp[1].split("_");
+            diagnosis_map = new HashMap<>();
+            for (String diagnosis: diagnoses)
+                diagnosis_map.put(diagnosis, 1);
+            this.RELATED_DIAGNOSIS_DICT.put(temp[0], diagnosis_map);
+        }
+
+        System.out.println("疾病过滤字典大小:" + this.RELATED_DIAGNOSIS_DICT.size());
+    }
+
+
 }

+ 11 - 1
algorithm/src/main/java/org/algorithm/core/neural/dataset/NNDataSetImplNonParallel.java

@@ -22,7 +22,17 @@ public class NNDataSetImplNonParallel extends NNDataSet {
         super(modelAndVersion);
     }
 
-    
+
+    @Override
+    public void readReSplitWordDict() {
+
+    }
+
+    @Override
+    public void readFilterDiagnosisDict() {
+
+    }
+
     @Override
     public float[] toFeatureVector(Map<String, Map<String, String>> inputs) {
         // inputs {症状名:{partbody:部位名, property:属性名, duration:时间类别, sex:性别值, age:年龄值}

+ 33 - 0
algorithm/src/main/java/org/algorithm/factory/RelationExtractionFactory.java

@@ -0,0 +1,33 @@
+package org.algorithm.factory;
+
+import org.algorithm.core.cnn.AlgorithmCNNExecutorPacs;
+import org.algorithm.core.cnn.model.RelationExtractionEnsembleModel;
+
+/**
+ * @Description:
+ * @Author: HUJING
+ * @Date: 2019/9/10 15:25
+ */
+public class RelationExtractionFactory {
+    private static RelationExtractionEnsembleModel relationExtractionEnsembleModelInstance = null;
+
+    public static AlgorithmCNNExecutorPacs getInstance() {
+        try {
+            relationExtractionEnsembleModelInstance = (RelationExtractionEnsembleModel) create(relationExtractionEnsembleModelInstance, RelationExtractionEnsembleModel.class);
+        } catch (InstantiationException inst) {
+            inst.printStackTrace();
+        } catch (IllegalAccessException ille) {
+            ille.printStackTrace();
+        }
+        return relationExtractionEnsembleModelInstance;
+    }
+
+    private static Object create(Object obj, Class cls) throws InstantiationException, IllegalAccessException {
+        if (obj == null) {
+            synchronized (cls) {
+                obj = cls.newInstance();
+            }
+        }
+        return obj;
+    }
+}

+ 5 - 3
algorithm/src/main/java/org/algorithm/test/ReEnsembleModelTest.java

@@ -18,7 +18,7 @@ public class ReEnsembleModelTest {
 
     public static void main(String[] args) {
         RelationExtractionEnsembleModel ensembleModel = new RelationExtractionEnsembleModel();
-
+        List<List<String>> result = new ArrayList<>();
         List<Triad> triads = new ArrayList<>();
         Triad triad_1 = new Triad();
         Lemma l_1 = new Lemma();
@@ -36,9 +36,11 @@ public class ReEnsembleModelTest {
 
         long start = System.nanoTime();
         for (int i=0; i<200; i++)  // 重复100次
-            triads = ensembleModel.execute("患者剧烈胸痛头痛失眠不安", triads);
+        {
+            result = ensembleModel.execute("患者剧烈胸痛头痛失眠不安", triads);
+        }
         long elapsedTime = System.nanoTime() - start;
-        System.out.println(triads.size());
+        System.out.println(result.size());
         System.out.println(elapsedTime);
     }
 }

+ 9 - 4
algorithm/src/main/java/org/algorithm/test/TensorflowExcutorTest.java

@@ -1,5 +1,6 @@
 package org.algorithm.test;
 
+import org.algorithm.core.neural.DiagnosisPredictExecutor;
 import org.algorithm.core.neural.SymptomPredictExecutor;
 import org.algorithm.util.Utils;
 
@@ -13,9 +14,9 @@ public class TensorflowExcutorTest {
         
         //TODO:change VitalPredictExcutor to test different executors
 //        VitalPredictExecutor excutor = new VitalPredictExecutor();
-        SymptomPredictExecutor excutor = new SymptomPredictExecutor();
+//        SymptomPredictExecutor excutor = new SymptomPredictExecutor();
 //        LisPredictExecutor excutor = new LisPredictExecutor();
-//        DiagnosisPredictExecutor excutor = new DiagnosisPredictExecutor();
+        DiagnosisPredictExecutor excutor = new DiagnosisPredictExecutor();
 //        PacsPredictExecutor excutor = new PacsPredictExecutor();
 //        DiagnosisToLisExecutor excutor = new DiagnosisToLisExecutor();
 //        DiagnosisToPacsExecutor excutor = new DiagnosisToPacsExecutor();
@@ -75,7 +76,11 @@ public class TensorflowExcutorTest {
         featureValues.put("age", "34");
         featureValues.put("negative", "有");
         featureValues.put("sn", "0");
-        aMap.put("踝关节疼痛", featureValues);
+
+        aMap.put("上臂远端疼痛", featureValues);
+        aMap.put("上肢远端青紫", featureValues);
+        aMap.put("肘部肿胀", featureValues);
+        aMap.put("外伤", featureValues);
 //        aMap.put("心悸", featureValues);
 //        aMap.put("气急", featureValues);
 //        aMap.put("头痛", featureValues);
@@ -87,7 +92,7 @@ public class TensorflowExcutorTest {
 //        for (Entry<String, Float> entry : result.entrySet()) {
 //            System.out.println(entry.getKey() + " : " + entry.getValue());
 //        }
-//        System.out.println(result);
+        System.out.println(result);
         Utils.top_k(10, result);
 
     }

+ 47 - 40
algorithm/src/main/java/org/algorithm/test/Test.java

@@ -1,49 +1,56 @@
 package org.algorithm.test;
 
+import java.util.*;
 
 public class Test {
-    
+
+
     public static void main(String[] args) {
-        
-//        Integer aa = new Integer(53);
-//        Integer bb = new Integer(954);
-//        float xx = 1.0f;
-//        for(int i=1; i< 955; i++) {
-//            xx = (float)(Math.round(1.0f * i / bb*100000))/100000;
-//            System.out.println(i+":"+xx);
-////        }
-//        String filePath = "/opt/models/model_version_replacement/model";
-//        int index = filePath.indexOf("model_version_replacement");
-//
-//        System.out.println(filePath.substring(0, index));
-//            public static void testJSONStrToJavaBeanObj(){
-//
-//        Student student = JSON.parseObject(JSON_OBJ_STR, new TypeReference<Student>() {});
-//        //Student student1 = JSONObject.parseObject(JSON_OBJ_STR, new TypeReference<Student>() {});//因为JSONObject继承了JSON,所以这样也是可以的
-//
-//        System.out.println(student.getStudentName()+":"+student.getStudentAge());
-//
-        String JSON_ARRAY_STR = "[{\"length\":4,\"offset\":0,\"property\":\"1\",\"text\":\"剑突下痛\",\"threshold\":0.0},{\"length\":2,\"offset\":4,\"property\":\"1\",\"text\":\"胀痛\",\"threshold\":0.0},{\"length\":2,\"offset\":6,\"property\":\"2\",\"text\":\"1天\",\"threshold\":0.0},{\"length\":1,\"offset\":8,\"text\":\",\",\"threshold\":0.0}]\n";
-//        JSONArray jsonArray = JSONArray.parseArray(JSON_ARRAY_STR);
-////        String jsonString = "{\"length\":4,\"offset\":0,\"property\":\"1\",\"text\":\"剑突下痛\",\"threshold\":0.0}";
-//
-//       for (int i = 0; i < jsonArray.size(); i++){
-//           JSONObject job = jsonArray.getJSONObject(i);
-//           LemmaInfo info = JSON.parseObject(job.toJSONString(), new TypeReference<LemmaInfo>() {});
-//           //Student student1 = JSONObject.parseObject(JSON_OBJ_STR, new TypeReference<Student>() {});//因为JSONObject继承了JSON,所以这样也是可以的
-//
-//           System.out.println(info.getLength()+":"+info.getText());
-//       }
-
-        int index = 0;
-        for (int i=0; i<5; i++)
-            for (int j = i+1; j< 6; j++){
-                System.out.println(i + "," + j);
-                index ++;
-            }
-
-        System.out.println(index);
+        List<Integer> data = new ArrayList<>();
+        data.add(1);
+        data.add(3);
+        data.add(5);
+        data.add(7);
+        Test t = new Test();
+
+        List<List<Integer>> workSpace = new ArrayList<>();
+        for (int i = 1; i < data.size(); i++) {
+            t.combinerSelect(data, new ArrayList<>(), workSpace, data.size(), i);
+        }
+
+        System.out.println(workSpace);
 
     }
 
+    /**
+     * 组合生成器
+     *
+     * @param data      原始数据
+     * @param workSpace 自定义一个临时空间,用来存储每次符合条件的值
+     * @param k         C(n,k)中的k
+     */
+    public <E> void combinerSelect(List<E> data, List<E> workSpace, List<List<E>> result, int n, int k) {
+        List<E> copyData;
+        List<E> copyWorkSpace = null;
+
+        if (workSpace.size() == k) {
+            for (E c : workSpace)
+                System.out.print(c);
+
+            result.add(new ArrayList<>(workSpace));
+            System.out.println();
+        }
+
+        for (int i = 0; i < data.size(); i++) {
+            copyData = new ArrayList<E>(data);
+            copyWorkSpace = new ArrayList<E>(workSpace);
+
+            copyWorkSpace.add(copyData.get(i));
+            for (int j = i; j >= 0; j--)
+                copyData.remove(j);
+            combinerSelect(copyData, copyWorkSpace, result, n, k);
+        }
+    }
+
 }
+

+ 46 - 0
algorithm/src/main/java/org/algorithm/test/TestDiagnosisFilter.java

@@ -0,0 +1,46 @@
+package org.algorithm.test;
+
+import org.algorithm.core.neural.dataset.NNDataSetImpl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author: bijl
+ * @Date: 2019/9/23 10:49
+ * @Description:
+ */
+public class TestDiagnosisFilter {
+
+    public static void main(String[] args) {
+        NNDataSetImpl dataSet = new NNDataSetImpl("diagnosisPredict.version");
+
+        dataSet.readFilterDiagnosisDict();  // 读取过滤表
+//        鼻炎|0|2|outpatient_556_IOE_1
+//        肺癌|1|2|outpatient_556_IOE_1
+//        胃肠炎|2|2|outpatient_556_IOE_1
+//        屈光不正|3|2|outpatient_556_IOE_1
+        // 构造方式:去查dictionaries.bin文件中outpatient_556_IOE_1,相关的疾病,形如上
+        float[][] predict = {{0.1f, 0.2f, 0.3f, 0.4f}};
+
+        // 构造输入
+        Map<String, Map<String, String>> inputs = new HashMap<>();
+        Map<String, String> featureMap = new HashMap<>();
+        featureMap.put("negative", "有");
+        featureMap.put("property", "11");
+
+        // 构造方式:去查filter_diagnoses.bin文件中与上述疾病相关的一个或多个特征,加入
+        inputs.put("上腹压痛", featureMap);  // 上腹压痛,只与,胃肠炎,相关
+        // 保存输入
+        dataSet.storeFeatureNames(inputs);
+
+        // 过滤疾病
+        Map<String, Float> result = dataSet.wrapAndFilter(predict);
+        Map<String, Float> result_no_filter = dataSet.basicWrap(predict);
+
+        System.out.println("无疾病过滤:" + result_no_filter);  // 期望输出 {鼻炎=0.1, 肺癌=0.2, 胃肠炎=0.3, 屈光不正=0.4}
+        System.out.println("疾病过滤:" + result);  // 期望输出{胃肠炎=0.3}
+
+
+    }
+}

+ 34 - 0
algorithm/src/main/java/org/algorithm/test/TestReSplit.java

@@ -0,0 +1,34 @@
+package org.algorithm.test;
+
+import org.algorithm.core.neural.dataset.NNDataSetImpl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 测试再分词
+ * @Author: bijl
+ * @Date: 2019/9/23 10:46
+ * @Description:
+ */
+public class TestReSplit {
+
+    public static void main(String[] args) {
+
+        NNDataSetImpl dataSet = new NNDataSetImpl("diagnosisPredict.version");
+
+        // 构造输入
+        Map<String, Map<String, String>> inputs = new HashMap<>();
+
+        Map<String, String> featureMap = new HashMap<>();
+        featureMap.put("negative", "有");
+        featureMap.put("property", "11");
+
+        inputs.put("幽门螺杆菌感染", featureMap);
+
+        // 对比再分词前后的变化
+        System.out.println("原来数据:" + inputs);
+        dataSet.reSplitWord(inputs);
+        System.out.println("再分词后数据:" + inputs);
+    }
+}

+ 15 - 0
algorithm/src/main/java/org/algorithm/test/TestRelationTreeUtils.java

@@ -0,0 +1,15 @@
+package org.algorithm.test;
+
+import org.algorithm.core.RelationTreeUtils;
+
+/**
+ * @Author: bijl
+ * @Date: 2019/9/5 17:07
+ * @Description:
+ */
+public class TestRelationTreeUtils {
+
+    public static void main(String[] args) {
+        RelationTreeUtils.test();
+    }
+}

文件差异内容过多而无法显示
+ 140 - 0
algorithm/src/main/java/org/algorithm/test/TestRuleCheckMachine.java


+ 1 - 1
algorithm/src/main/java/org/algorithm/util/MysqlConnector.java

@@ -45,7 +45,7 @@ public class MysqlConnector {
     
     /**
      * 执行sql语句
-     * @param sql
+     * @param sqls
      */
     public void executeBatch(List<String> sqls) {
         Statement stmt = null;

+ 1 - 1
algorithm/src/main/resources/algorithm.properties

@@ -2,7 +2,7 @@
 
 #basicPath=E:/project/push/algorithm/src/main/models/model_version_replacement/model
 basicPath=/opt/models/dev/models/model_version_replacement/model
-#basicPath=E:/xxx/model_version_replacement/model
+#basicPath=E:/re_models/model_version_replacement/model
 
 ############################### current model version ################################
 diagnosisPredict.version=outpatient_556_IOE_1

+ 34 - 0
common-push/src/main/java/org/diagbot/common/push/cache/ApplicationCacheUtil.java

@@ -9,8 +9,10 @@ import org.diagbot.nlp.util.NlpCache;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 public class ApplicationCacheUtil {
 
@@ -26,6 +28,8 @@ public class ApplicationCacheUtil {
     public static Map<String, List<Rule>> kl_rule_filter_map = null;
     //危险值提醒
     public static Map<String, RuleApp> kl_rule_app_filter_map = null;
+    //pacs关系抽取过滤
+    public static Map<String, Map<String, String>> kl_diagnose_detail_filter_map = null;
 
     public static Map<String, Map<String, String>> getStandard_info_synonym_map() {
         if (standard_info_synonym_map == null) {
@@ -203,4 +207,34 @@ public class ApplicationCacheUtil {
             }
         }
     }
+
+    public static Map<String, Map<String, String>> getKl_diagnose_detail_filter_map() {
+        if (kl_diagnose_detail_filter_map == null) {
+            create_kl_diagnose_detail_filter_map();
+        }
+        return kl_diagnose_detail_filter_map;
+    }
+
+
+    public static void create_kl_diagnose_detail_filter_map() {
+        kl_diagnose_detail_filter_map = new HashMap<>();
+        Map<String, String> diagnoseDetailRelationMap = new HashMap<>();
+        Set<String> diagnoseDetailRelation = new HashSet<>();
+        Configuration configuration = new DefaultConfig();
+        List<String> fileContents = configuration.readFileContents("bigdata_diagnose_detail_filter.dict");
+        for (String line : fileContents) {
+            String[] content = line.split("\\|", -1);
+            String[] relations = content[1].split("、");
+            for (String relation : relations) {
+                if (diagnoseDetailRelation.add(relation)) {
+                    if (kl_diagnose_detail_filter_map.get(content[0]) == null) {
+                        diagnoseDetailRelationMap.put(relation, relation);
+                        kl_diagnose_detail_filter_map.put(content[0], diagnoseDetailRelationMap);
+                    } else {
+                        kl_diagnose_detail_filter_map.get(content[0]).put(relation, relation);
+                    }
+                }
+            }
+        }
+    }
 }

+ 21 - 28
common-push/src/main/java/org/diagbot/common/push/cache/CacheFileManager.java

@@ -22,9 +22,9 @@ import java.util.*;
 public class CacheFileManager {
     Logger logger = LoggerFactory.getLogger(CacheFileManager.class);
 
-    private String user = "root";
-    private String password = "lantone";
-    private String url = "jdbc:mysql://192.168.2.122:3306/med?useUnicode=true&characterEncoding=UTF-8";
+    private String user = "teamdata";
+    private String password = "jiO2rfnYhg";
+    private String url = "jdbc:mysql://192.168.2.121:3306/med?useUnicode=true&characterEncoding=UTF-8";
 
     private String path = "";
 
@@ -164,6 +164,18 @@ public class CacheFileManager {
 
             fw = new FileWriter(path + "classify.dict");
             fw.close();
+
+            sql = "select name, type from kl_library_info_pacs order by name";
+            st = conn.createStatement();
+            rs = st.executeQuery(sql);
+            fw = new FileWriter(path + "pacs-tc.dict");
+            while (rs.next()) {
+                r1 = rs.getString(1);
+                r2 = rs.getString(2);
+                fw.write(encrypDES.encrytor(r1 + "|9|"+ r2 + "|" + r1));
+                fw.write("\n");
+            }
+            fw.close();
         } catch (IOException ioe) {
             ioe.printStackTrace();
         } catch (SQLException sqle) {
@@ -237,7 +249,7 @@ public class CacheFileManager {
             }
             fw.close();
             //疾病科室信息
-            sql = "SELECT k1.lib_name diag_name, k2.lib_name dept_name FROM kl_concept_common kcc, kl_concept k1, kl_concept k2 " +
+            sql = "SELECT k1.lib_name diag_name, k2.lib_name dept_name FROM kl_disease kcc, kl_concept k1, kl_concept k2 " +
                     "where kcc.concept_id = k1.id and kcc.dept_id = k2.id " +
                     "and k1.lib_type = 18 and kcc.dept_id  is not null";
             st = conn.createStatement();
@@ -281,7 +293,7 @@ public class CacheFileManager {
         try {
             EncrypDES encrypDES = new EncrypDES();
             //疾病科室
-            String sql = "SELECT k1.lib_name diag_name, k2.lib_name dept_name FROM kl_concept_common kcc, kl_concept k1, kl_concept k2 " +
+            String sql = "SELECT k1.lib_name diag_name, k2.lib_name dept_name FROM kl_disease kcc, kl_concept k1, kl_concept k2 " +
                     "where kcc.concept_id = k1.id and kcc.dept_id = k2.id " +
                     "and k1.lib_type = 18 and kcc.dept_id  is not null";
             st = conn.createStatement();
@@ -387,33 +399,14 @@ public class CacheFileManager {
             }
             fw.close();
 
-            //化验辅检体征性别年龄
-            sql = "SELECT k1.lib_name, k1.lib_type, kcc.sex_type, kcc.min_age, kcc.max_age " +
-                    "FROM kl_concept_common kcc, kl_concept k1 " +
-                    "where kcc.concept_id = k1.id " +
-                    "and k1.lib_type in (1, 18,12,16,33,35)";
+            sql = "SELECT type,relation FROM `kl_diagnose_detail` WHERE type = 4 AND LENGTH(relation) > 0 GROUP BY relation";
             st = conn.createStatement();
             rs = st.executeQuery(sql);
-            fw = new FileWriter(path + "bigdata_lpv_sex_age_filter.dict");//化验辅检体征相关文件
+            fw = new FileWriter(path + "bigdata_diagnose_detail_filter.dict");
             while (rs.next()) {
-                r1 = rs.getString(1);
+                r1 = String.valueOf(rs.getInt(1));
                 r2 = rs.getString(2);
-                r3 = rs.getString(3);
-                r4 = rs.getString(4);
-                r5 = rs.getString(5);
-                if ("18".equals(r2)) {//诊断
-                    r2 = "2";
-                }
-                if ("12".equals(r2)) {//化验
-                    r2 = "4";
-                }
-                if ("16".equals(r2)) {//辅检
-                    r2 = "5";
-                }
-                if ("33".equals(r2) | "35".equals(r2)) {//体征
-                    r2 = "3";
-                }
-                fw.write(encrypDES.encrytor(r1 + "|" + r2 + "|" + r3 + "|" + r4 + "|" + r5));
+                fw.write(encrypDES.encrytor(r1+ "|" + r2));
                 fw.write("\n");
             }
             fw.close();

+ 16 - 42
common-push/src/main/java/org/diagbot/common/push/filter/ClassifyDiag.java

@@ -22,34 +22,6 @@ public class ClassifyDiag {
     //每个诊断所在的级别缓存
     Map<String, Integer> diagClassifyJiCache = CacheUtil.getDiagClassifyJiCache();
 
-   /* public static void main(String[] args) {
-
-        List<String> disList = new LinkedList<>();
-        String[] disArray = {"急性胰腺炎","冠心病","急性冠状动脉综合征","急性非ST段抬高型心肌梗死","急性ST段抬高型心肌梗死"
-        ,"三度房室传导阻滞","心力衰竭","急性心力衰竭"};
-         disList = Arrays.asList(disArray);
-        System.out.println("输入的诊断"+disList);
-        List<FeatureRate> inintFeature = new ArrayList<>();
-        Double inintNumber = 0.95;
-        String rate = "";
-        for (String dis:disList) {
-            FeatureRate featureRate = new FeatureRate();
-            featureRate.setFeatureName(dis);
-            inintNumber = inintNumber - 0.1;
-            rate = String.valueOf(inintNumber);
-            featureRate.setRate(rate);
-            inintFeature.add(featureRate);
-        }
-
-        ClassifyDiag classifyDiag = new ClassifyDiag();
-        List<FeatureRate> classify = classifyDiag.diagClassify(inintFeature);
-        System.out.println("hao hai you");
-        for (FeatureRate d:classify) {
-            System.out.println(d.getFeatureName()+"\t"+d.getRate()+"\t"+d.getExtraProperty());
-        }
-
-    }*/
-
     /**
      * 根据诊断依据规则过滤诊断
      * @param graphResponseData 把过滤的诊断包装在这个对象里
@@ -91,16 +63,6 @@ public class ClassifyDiag {
                 String desc = featureRate.getDesc();
                 Map<String,Object> d = new HashMap<>();
                 if(desc != null){
-                   /* JSONObject jsonObject = JSONObject.parseObject(desc);
-                    d = jsonObject;
-                    if(d.keySet().size() == 1 && "警惕".equals(d.keySet().toArray()[0])){
-                        highDiagList.add(featureName);
-                    }else if(d.keySet().size() == 1 && ("鉴别诊断".equals(d.keySet().toArray()[0])
-                            || "页面急诊".equals(d.keySet().toArray()[0])) || "急诊".equals(d.keySet().toArray()[0])){
-                        diffDiagList.add(featureName);
-                    }else {
-                        queDiagList.add(featureName);
-                    }*/
                    if(desc.contains("确诊") || desc.contains("拟诊")){
                        queDiagList.add(featureName);
                    }else {
@@ -117,7 +79,7 @@ public class ClassifyDiag {
                 FeatureRate featureRate = updateFeatures.get(j);
                 String featureName = featureRate.getFeatureName();
                 int i = highDiagList.indexOf(featureName);
-                if(i >= 0){
+                if(i >= 0 && featureRate.getDesc() != null){
                     finalDiagList.add(featureRate);
                 }
             }
@@ -128,7 +90,7 @@ public class ClassifyDiag {
                 FeatureRate featureRate = updateFeatures.get(j);
                 String featureName = featureRate.getFeatureName();
                 int i = diffDiagList.indexOf(featureName);
-                if(i >= 0){
+                if(i >= 0 && featureRate.getDesc() != null){
                     finalDiagList.add(featureRate);
                 }
             }
@@ -211,6 +173,8 @@ public class ClassifyDiag {
                             bigDataIDiagList.add(featureName);
                         }else if("Ⅱ".equals(s)){
                             bigDataIIDiagList.add(featureName);
+                        }else {
+                            bigDataIDiagList.add(featureName);
                         }
                     }else {
                         bigDataIDiagList.add(featureName);
@@ -218,13 +182,23 @@ public class ClassifyDiag {
                 }
             }
         }
-        finalDiagList.addAll(neoDiagList);
+//        finalDiagList.addAll(neoDiagList);
         finalDiagList.addAll(bigDataIDiagList);
         finalDiagList.addAll(bigDataIIDiagList);
+        if(neoDiagList !=null && neoDiagList.size()>0){
+            for (String diag:neoDiagList) {
+                for (FeatureRate feature:updateFeatureRates) {
+                    if(diag.equals(feature.getFeatureName())&& "neo4j".equals(feature.getSource())){
+                        finalDiagFeature.add(feature);
+                        break;
+                    }
+                }
+            }
+        }
         if(finalDiagList != null && finalDiagList.size()>0){
             for (String diag:finalDiagList){
                 for (FeatureRate f:updateFeatureRates) {
-                    if(diag.equals(f.getFeatureName())){
+                    if(diag.equals(f.getFeatureName())&& f.getSource()==null){
                         finalDiagFeature.add(f);
                         break;
                     }

+ 2 - 0
common-push/src/main/java/org/diagbot/common/push/filter/pretreat/Pretreatment.java

@@ -80,4 +80,6 @@ public abstract class Pretreatment {
         }
         return -1;
     }
+
+
 }

+ 39 - 5
common-push/src/main/java/org/diagbot/common/push/filter/pretreat/PretreatmentLis.java

@@ -1,25 +1,47 @@
 package org.diagbot.common.push.filter.pretreat;
 
+import org.apache.commons.lang3.StringUtils;
 import org.diagbot.common.push.bean.PreResult;
+import org.diagbot.nlp.participle.ParticipleUtil;
 import org.diagbot.nlp.participle.word.Lexeme;
 import org.diagbot.nlp.participle.word.LexemePath;
 import org.diagbot.nlp.util.NegativeEnum;
 import org.diagbot.nlp.util.NlpUtil;
 
-import java.lang.reflect.Array;
 import java.util.List;
 
 public class PretreatmentLis extends Pretreatment {
     private String join_symbols = ";:;:";
+    protected NegativeEnum[] lisResult = new NegativeEnum[]{NegativeEnum.LIS_RESULT};
 
-    public List<PreResult> analyze(String content) throws java.io.IOException{
-        return super.analyzeDefault(content);
+    public List<PreResult> analyze(String content) throws java.io.IOException {
+        List<PreResult> preResults = super.analyzeDefault(content);
+        LexemePath<Lexeme> lexemes = ParticipleUtil.participle(content);
+        for (int i = 0; i < lexemes.size(); i++) {
+            Lexeme l = lexemes.get(i);
+            if (NlpUtil.isFeature(l.getProperty(), lisResult)) {
+                cursor = i;
+                PreResult result = new PreResult();
+                result = findPreResultPub(lexemes, result);
+                if (result != null) {
+                    result.setOtherValue(l.getText());
+                    preResults.add(result);
+                }
+            }
+        }
+        return preResults;
     }
 
     public PreResult createPreResult(LexemePath<Lexeme> lexemes, Lexeme lexeme, int index) {
         PreResult result = new PreResult();
         double value = findNumberValue(lexemes, lexeme, index);
         if (value == -1) return null;
+        result.setValue(String.valueOf(value));
+        result.setUnits(lexeme.getText());
+        return findPreResultPub(lexemes, result);
+    }
+
+    public PreResult findPreResultPub(LexemePath<Lexeme> lexemes, PreResult result) {
         //继续往前找化验明细项
         if (cursor > 0) cursor--;
         Lexeme leftLexeme = lexemes.get(cursor);
@@ -38,6 +60,7 @@ public class PretreatmentLis extends Pretreatment {
         } else {
             return null;
         }
+
         //查找化验套餐
         int position = cursor - 1;
         while (position > -1) {
@@ -48,8 +71,19 @@ public class PretreatmentLis extends Pretreatment {
             }
             position--;
         }
-        result.setValue(String.valueOf(value));
-        result.setUnits(lexeme.getText());
+
+        if (StringUtils.isEmpty(result.getUniqueName())){
+            if (StringUtils.isNotEmpty(result.getDetailName()) && StringUtils.isNotEmpty(result.getName())){
+                result.setUniqueName(result.getName() + "--" + result.getDetailName());
+            } else if (StringUtils.isNotEmpty(result.getDetailName())){
+                result.setUniqueName(result.getDetailName());
+            } else if (StringUtils.isNotEmpty(result.getName())){
+                result.setUniqueName(result.getName());
+            } else {
+                return null;
+            }
+        }
+
         return result;
     }
 

+ 83 - 6
common-push/src/main/java/org/diagbot/common/push/filter/pretreat/PretreatmentPacs.java

@@ -6,13 +6,16 @@ import org.diagbot.nlp.participle.word.Lexeme;
 import org.diagbot.nlp.participle.word.LexemePath;
 import org.diagbot.nlp.util.NegativeEnum;
 import org.diagbot.nlp.util.NlpUtil;
+import org.springframework.util.StringUtils;
 
 import java.util.List;
 
 public class PretreatmentPacs extends Pretreatment {
-    protected NegativeEnum[] nees_pacs_result = new NegativeEnum[]{NegativeEnum.PACS_RESULT};
-    protected NegativeEnum[] nees_pacs_name = new NegativeEnum[]{NegativeEnum.PACS_NAME};
-    public List<PreResult> analyze(String content) throws java.io.IOException{
+    protected NegativeEnum[] nees_pacs_result = new NegativeEnum[] { NegativeEnum.PACS_RESULT };
+    protected NegativeEnum[] nees_pacs_name = new NegativeEnum[] { NegativeEnum.PACS_NAME };
+    private String join_symbols = ";:;:";
+
+    public List<PreResult> analyze(String content) throws java.io.IOException {
         List<PreResult> preResultList = super.analyzeDefault(content);
         //pacs除了数值型需要转, 还需要对部分检查结果提取,以便做危机警示
         LexemePath<Lexeme> lexemes = ParticipleUtil.participle(content);
@@ -34,18 +37,92 @@ public class PretreatmentPacs extends Pretreatment {
                     }
                     c--;
                 }
-
+            } else if (NlpUtil.isFeature(l.getProperty(), nees_time_and_unit) && i > 0) {
+                PreResult result = data2Object(lexemes, l, i, l.getProperty());
+                if (result != null) {
+                    preResultList.add(result);
+                }
             }
         }
-
         return preResultList;
     }
 
     public PreResult createPreResult(LexemePath<Lexeme> lexemes, Lexeme lexeme, int index) {
-        return super.createDefaultPreResult(lexemes, lexeme, index);
+        double value = findNumberValue(lexemes, lexeme, index);
+        if (value == -1) {
+            return null;
+        }
+//        //继续往前找本体
+//        String text = findBodyValue(lexemes, lexeme, index);
+//        if (StringUtils.isEmpty(text)) {
+//            return null;
+//        }
+        PreResult result = new PreResult();
+        result.setValue(String.valueOf(value));
+        result.setUnits(lexeme.getText());
+        return getPreResultPub(lexemes, result);
     }
 
     public String findBodyValue(LexemePath<Lexeme> lexemes, Lexeme lexeme, int index) {
         return null;
     }
+
+    public PreResult getPreResultPub(LexemePath<Lexeme> lexemes, PreResult result) {
+        //继续往前找辅检明细项
+        if (cursor > 0) {
+            cursor--;
+        }
+        Lexeme leftLexeme = lexemes.get(cursor);
+        if (join_symbols.contains(leftLexeme.getText())) {
+            if (cursor > 0) {
+                cursor--;
+                leftLexeme = lexemes.get(cursor);
+            } else {
+                return null;
+            }
+        }
+        if (NlpUtil.isFeature(leftLexeme.getProperty(), new NegativeEnum[] { NegativeEnum.PACS_NAME })) {
+            result.setDetailName(NlpUtil.concept(leftLexeme, NegativeEnum.PACS_NAME));
+        } else if (NlpUtil.isFeature(leftLexeme.getProperty(), new NegativeEnum[] { NegativeEnum.PACS_NAME })) {
+            result.setUniqueName(NlpUtil.concept(leftLexeme, NegativeEnum.PACS_NAME));
+        } else {
+            return null;
+        }
+        return result;
+    }
+
+    protected double findNumberValue(LexemePath<Lexeme> lexemes, Lexeme lexeme, int index) {
+        if (index < 1) {
+            return -1;
+        }
+        cursor = index - 1;
+        Lexeme leftLexeme = lexemes.get(cursor);
+        if (isNumberString(leftLexeme)) {
+            String[] numbersSplit = leftLexeme.getText().split("\\*");
+            try {
+                if (numbersSplit.length == 2) {
+                    return Double.valueOf(numbersSplit[0]) * Double.valueOf(numbersSplit[1]);
+                } else if (numbersSplit.length == 3) {
+                    return Double.valueOf(numbersSplit[0]) * Double.valueOf(numbersSplit[1])
+                            * Double.valueOf(numbersSplit[2]);
+                } else {
+                    return -1;
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return -1;
+    }
+
+    public static boolean isNumberString(Lexeme l) {
+        if (l == null) {
+            return false;
+        }
+        if (NlpUtil.isFeature(l.getProperty(), new NegativeEnum[] { NegativeEnum.DIGITS })
+                && l.getText().indexOf("*") != -1) {
+            return true;
+        }
+        return false;
+    }
 }

+ 22 - 0
common-push/src/main/java/org/diagbot/common/push/util/PushConstants.java

@@ -1,5 +1,8 @@
 package org.diagbot.common.push.util;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * @ClassName org.diagbot.bigdata.util.BigDataConstants
  * @Description TODO
@@ -38,4 +41,23 @@ public class PushConstants {
     public final static String result_mapping_vital = "resultMappingVitalMap";          //推送体征结果名称映射
     public final static String result_mapping_diag = "resultMappingDiagMap";          //推送疾病科室名称映射
     public final static String result_mapping_filter = "resultMappingFilterMap";          //推送结果年龄 性别过滤
+
+    //关系抽取property_id对应property_name
+    public final static Map<String,String> featureTypeMap = new HashMap<String,String>(){{
+        put("80","辅检其他");
+        put("9","单位");
+        put("2","时间");
+        put("3","部位");
+        put("7","反意或虚拟");
+        put("16","辅检项目");
+        put("17","辅检结果");
+        put("81","属性");
+        put("82","方位");
+        put("83","形容词");
+        put("84","局部结构");
+        put("85","属性值");
+        put("86","表现");
+        put("28","字母与数值");
+        put("87","正常表现");
+    }};
 }

+ 15 - 23
common-push/src/main/java/org/diagbot/common/push/work/ParamsDataProxy.java

@@ -1,5 +1,8 @@
 package org.diagbot.common.push.work;
 
+import org.algorithm.core.cnn.AlgorithmCNNExecutor;
+import org.algorithm.core.cnn.AlgorithmCNNExecutorPacs;
+import org.algorithm.factory.RelationExtractionFactory;
 import org.apache.commons.lang3.StringUtils;
 import org.diagbot.common.push.bean.SearchData;
 import org.diagbot.common.push.util.PushConstants;
@@ -10,9 +13,7 @@ import org.diagbot.nlp.util.NegativeEnum;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.servlet.http.HttpServletRequest;
 import java.util.*;
-import java.util.regex.Pattern;
 
 /**
  * @ClassName org.diagbot.bigdata.work.ParamsDataProxy
@@ -23,25 +24,6 @@ import java.util.regex.Pattern;
  **/
 public class ParamsDataProxy {
     Logger logger = LoggerFactory.getLogger(ParamsDataProxy.class);
-    //标准词只处理的词性
-    public static NegativeEnum[] negativeEnums = new NegativeEnum[] { NegativeEnum.VITAL_INDEX, NegativeEnum.SYMPTOM
-            , NegativeEnum.DIGITS, NegativeEnum.EVENT_TIME, NegativeEnum.UNIT, NegativeEnum.DIAG_STAND
-            , NegativeEnum.OTHER};
-    //标准词处理的三元组
-    public static NegativeEnum[][] negativeEnumTriple = {
-            { NegativeEnum.VITAL_INDEX, NegativeEnum.DIGITS, NegativeEnum.UNIT },
-            { NegativeEnum.VITAL_INDEX, NegativeEnum.DIGITS, NegativeEnum.EVENT_TIME },
-            { NegativeEnum.SYMPTOM, NegativeEnum.DIGITS, NegativeEnum.UNIT },
-            { NegativeEnum.SYMPTOM, NegativeEnum.DIGITS, NegativeEnum.EVENT_TIME },
-            { NegativeEnum.DIAG_STAND, NegativeEnum.DIGITS, NegativeEnum.UNIT },
-            { NegativeEnum.DIAG_STAND, NegativeEnum.DIGITS, NegativeEnum.EVENT_TIME },
-            { NegativeEnum.DIAG_STAND, NegativeEnum.DIGITS, NegativeEnum.OTHER }
-    };
-    //标准词处理的二元组
-    public static NegativeEnum[][] negativeEnumTwoTuple = {
-            { NegativeEnum.VITAL_INDEX, NegativeEnum.DIGITS },
-            { NegativeEnum.SYMPTOM, NegativeEnum.DIGITS }
-    };
 
     public void createNormalInfo(SearchData searchData) throws Exception {
         //计算年龄区间
@@ -138,6 +120,16 @@ public class ParamsDataProxy {
             featuresList = fa.start(searchData.getDiag(), FeatureType.DIAG);
             paramFeatureInit(searchData, featuresList);
         }
+        if (!StringUtils.isEmpty(searchData.getPacs())) {
+            //关系抽取模型
+            AlgorithmCNNExecutorPacs algorithmCNNExecutor = RelationExtractionFactory.getInstance();
+            RelationExtractionUtil re = new RelationExtractionUtil();
+            //Pacs原始分词结果
+            List<List<String>> execute = algorithmCNNExecutor.execute(searchData.getPacs(), re.createTriad(searchData));
+            if (execute != null && execute.size() > 0) {
+                re.addToSearchDataInputs(execute, searchData);
+            }
+        }
     }
 
     /**
@@ -248,10 +240,10 @@ public class ParamsDataProxy {
                 map.put("concept", String.valueOf(featureMap.get("concept")));
                 if (Constants.default_negative.equals(featureMap.get("negative"))) {
                     if (map.get("featureType").equals(Constants.feature_type_time)) {
-                        searchData.getInputs().put("时间", map);
+//                        searchData.getInputs().put("时间", map);
                     } else {
                         if (searchData.getInputs().get(map.get("feature_name")) == null) {
-                            if (i < 5) {
+                            if (i < 8) {
                                 searchData.getInputs().put(map.get("feature_name"), map);
                             }
                             searchData.getGraphInputs().put(map.get("feature_name"), map);

+ 92 - 0
common-push/src/main/java/org/diagbot/common/push/work/RelationExtractionUtil.java

@@ -0,0 +1,92 @@
+package org.diagbot.common.push.work;
+
+import org.algorithm.core.cnn.entity.Lemma;
+import org.algorithm.core.cnn.entity.Triad;
+import org.diagbot.common.push.bean.SearchData;
+import org.diagbot.common.push.cache.ApplicationCacheUtil;
+import org.diagbot.common.push.util.PushConstants;
+import org.diagbot.nlp.participle.ParticipleUtil;
+import org.diagbot.nlp.participle.word.Lexeme;
+import org.diagbot.nlp.participle.word.LexemePath;
+import org.diagbot.nlp.util.Constants;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description:
+ * @Author: HUJING
+ * @Date: 2019/9/9 17:30
+ */
+public class RelationExtractionUtil {
+    public List<Triad> createTriad(SearchData searchData) throws IOException {
+        List<Triad> triads = new ArrayList<>();
+        String[] pacsSplits = searchData.getPacs().trim().split("。|\n");
+        List<Lemma> lemmaList = new ArrayList<>();
+        Lemma lemma = null;
+        for (String pacsSplit : pacsSplits) {
+            LexemePath<Lexeme> pacsLexemes = ParticipleUtil.participlePacs(pacsSplit);
+            for (int i = 0; i < pacsLexemes.size(); i++) {
+                //跳过非医学词
+                if (Constants.word_property_other.equals(pacsLexemes.get(i).getProperty())) {
+                    continue;
+                }
+                lemma = new Lemma();
+                lemma.setText(pacsLexemes.get(i).getText());
+                lemma.setPosition(String.valueOf(pacsLexemes.get(i).getOffset()) + "," + (Integer.valueOf(pacsLexemes.get(i).getOffset() + pacsLexemes.get(i).getLength()) - 1));
+                lemma.setProperty(PushConstants.featureTypeMap.get(pacsLexemes.get(i).getProperty()));
+                lemmaList.add(lemma);
+            }
+        }
+        for (int i = 0; i < lemmaList.size() - 1; i++) {
+            for (int j = i + 1; j < lemmaList.size(); j++) {
+                Triad triad = new Triad();
+                triad.setL_1(lemmaList.get(i));
+                triad.setL_2(lemmaList.get(j));
+                triads.add(triad);
+            }
+        }
+        return triads;
+    }
+
+    public void addToSearchDataInputs(List<List<String>> relationExtractionContents, SearchData searchData) throws Exception {
+        StringBuffer sb = null;
+        for (List<String> contents : relationExtractionContents) {
+            sb = new StringBuffer();
+            for (String content : contents) {
+                sb.append(content);
+            }
+            if (isExist(sb.toString())) {
+                Map<String, String> map = new HashMap<>();
+                map.put("featureType", "5");
+                map.put("featureName", sb.toString());
+                map.put("property", "17");
+                map.put("concept", sb.toString());
+                //全是有
+                map.put("negative", Constants.default_negative);
+                if (searchData.getInputs().get(map.get("featureName")) == null) {
+                    searchData.getInputs().put(map.get("featureName"), map);
+                }
+            }
+        }
+    }
+
+    /**
+     * 关系抽取输出的content是否在已有诊断依据中存在
+     * @param content
+     * @return
+     */
+    public boolean isExist(String content){
+        Map<String, Map<String, String>> kl_diagnose_detail_filter_map = ApplicationCacheUtil.getKl_diagnose_detail_filter_map();
+        if (kl_diagnose_detail_filter_map.get("4") != null){
+            if (kl_diagnose_detail_filter_map.get("4").containsKey(content)){
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

+ 6 - 0
graph-web/src/main/java/org/diagbot/graphWeb/work/GraphCalculate.java

@@ -60,6 +60,12 @@ public class GraphCalculate {
                 }
             }
         }
+        Map<String, Map<String, String>> inputsMap = searchData.getInputs();
+        if(inputsMap != null && inputsMap.size()>0){
+            if(inputsMap.keySet()!=null && inputsMap.keySet().size()>0){
+                ss.addAll(inputsMap.keySet()) ;
+            }
+        }
         logger.info("从分词系统接收到的词 :" + ss);
         System.out.println("Participle takes: " + (System.currentTimeMillis()-starttime)/1000d + 's');
         List<String> featureTypeList = Arrays.asList(searchData.getFeatureTypes());

+ 1 - 1
graph-web/src/main/java/org/diagbot/graphWeb/work/ScaleCalculate.java

@@ -109,7 +109,7 @@ public class ScaleCalculate {
 
                 groupLists.add(groupResults);
             }
-            String text = null;
+            String text = "";
             Map<String, Object> calculate = (Map<String, Object>) data.get("calculate");
             List<Map<String, Object>> rangeList = (List<Map<String, Object>>) calculate.get("range");
             for (Map<String, Object> range : rangeList) {

+ 1 - 1
graph/src/main/resources/bolt.properties

@@ -5,7 +5,7 @@ pass_235 = diagbot@20180822
 
 # neo4j bolt credentials
 #\u7EBF\u4E0A\u4F7F\u7528
-bolt.uri=bolt://192.168.2.123
+bolt.uri=bolt://192.168.2.233
 bolt.user=neo4j
 bolt.passwd=root
 

+ 3 - 3
graphdb/src/main/java/org/diagbot/service/impl/KnowledgeServiceImpl.java

@@ -55,9 +55,9 @@ public class    KnowledgeServiceImpl implements KnowledgeService {
     private KnowledgeMapper knowledgeMapper;
 
     private List<BaseNode> baseNodes;
-    private String user = "root";
-    private String password = "lantone";
-    private String url = "jdbc:mysql://192.168.2.241:3306/med?useUnicode=true&characterEncoding=UTF-8";
+    private String user = "teamdata";
+    private String password = "jiO2rfnYhg";
+    private String url = "jdbc:mysql://192.168.2.121:3306/med?useUnicode=true&characterEncoding=UTF-8";
     private Pageable pageable;
     /**
      * 处理症状节点相关的申请

+ 1 - 1
graphdb/src/main/resources/application.yml

@@ -6,7 +6,7 @@ spring:
     active: local
   data:
     neo4j:
-      uri: bolt://192.168.2.123:7687
+      uri: bolt://192.168.2.233:7687
       username: neo4j
       password: root
 

+ 60 - 51
nlp-web/src/main/java/org/diagbot/nlp/controller/FeatureController.java

@@ -28,13 +28,18 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 
 import javax.servlet.http.HttpServletRequest;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 @Controller
 @RequestMapping("/feature")
 public class FeatureController extends BaseController<Feature, FeatureWrapper, Long> {
     private String[] negative_words = Constants.negative_words;
-
+    //体征提取范围
+    private String featureNum;
     private Map<String, String> propelSymptom = null;
     private Map<String, String> propelDiag = null;
     private Map<String, String> propelVital= null;
@@ -146,60 +151,64 @@ public class FeatureController extends BaseController<Feature, FeatureWrapper, L
             Map<String, String> propel = null;
             List<Map<String, Object>> data = new ArrayList<>();
 
+           /* PropertiesUtil propertiesUtil = new PropertiesUtil("nlp.properties");
+            featureNum = propertiesUtil.getProperty("push.feature.num");*/
             FeatureAnalyze sa = new FeatureAnalyze();
             for (String featureType : featureTypes.split(",")) {
-                for (Info info : docInfos) {
-                    switch (FeatureType.parse(featureType)) {
-                        case SYMPTOM:
-                            content = info.getPresent();
-                            propel = propelSymptom;
-                            break;
-                        case TIME:
-                            content = info.getPresent();
-                            propel = propelSymptom;
-                            break;
-                        case FEATURE:
-                            content = info.getPresent();
-                            propel = propelSymptom;
-                            break;
-                        case VITAL:
-                            content = info.getVital();
-                            propel = propelVital;
-                            break;
-                        case PACS:
-                            content = info.getPacs();
-                            propel = propelPacs;
-                            break;
-                        case LIS:
-                            content = info.getLis();
-                            propel = propelLis;
-                            break;
-                        case DIAG:
-                            content = info.getDiag();
-                            propel = propelDiag;
-                            break;
-                    }
-                    featureList = sa.start(content, FeatureType.parse(featureType));
-
-                    if (featureList == null) {
-                        continue;
-                    }
-                    for (int i = 0; i < featureList.size(); i++) {
-                        featureMap = featureList.get(i);
-                        featureMap.put("rdn", info.getRdn());
-                        featureMap.put("age", StringUtils.isEmpty(info.getAge())?"0":info.getAge());
-                        featureMap.put("sex", info.getSex());
-                        featureMap.put("resource_type", info.getResourceType());
-
-                        if (propel.get(featureMap.get("feature_name")) == null) {
-                            featureMap.put("is_push", "0");
-                        } else {
-                            featureMap.put("is_push", "1");
+                for (String feature : featureNum.split(",")) {
+                    /*sa.setFeatureNum(feature);*/
+                    for (Info info : docInfos) {
+                        switch (FeatureType.parse(featureType)) {
+                            case SYMPTOM:
+                                content = info.getPresent();
+                                propel = propelSymptom;
+                                break;
+                            case TIME:
+                                content = info.getPresent();
+                                propel = propelSymptom;
+                                break;
+                            case FEATURE:
+                                content = info.getPresent();
+                                propel = propelSymptom;
+                                break;
+                            case VITAL:
+                                content = info.getVital();
+                                propel = propelVital;
+                                break;
+                            case PACS:
+                                content = info.getPacs();
+                                propel = propelPacs;
+                                break;
+                            case LIS:
+                                content = info.getLis();
+                                propel = propelLis;
+                                break;
+                            case DIAG:
+                                content = info.getDiag();
+                                propel = propelDiag;
+                                break;
+                        }
+                        featureList = sa.start(content, FeatureType.parse(featureType));
+                        if (featureList == null) {
+                            continue;
+                        }
+                        for (int i = 0; i < featureList.size(); i++) {
+                            featureMap = featureList.get(i);
+                            featureMap.put("rdn", info.getRdn() + "_" + feature);
+                            featureMap.put("age", StringUtils.isEmpty(info.getAge()) ? "0" : info.getAge());
+                            featureMap.put("sex", info.getSex());
+                            featureMap.put("resource_type", info.getResourceType());
+                            if (propel.get(featureMap.get("feature_name")) == null) {
+                                featureMap.put("is_push", "0");
+                            } else {
+                                featureMap.put("is_push", "1");
+                            }
+                            data.add(featureMap);
                         }
-                        data.add(featureMap);
-                    }
 
+                    }
                 }
+
             }
 
             MysqlJdbc jdbc = new MysqlJdbc(env.getProperty("spring.datasource.username"),

+ 1 - 1
nlp-web/src/main/java/org/diagbot/nlp/dao/xml/InfoMapper.xml

@@ -113,7 +113,7 @@
 	<select id="selectListWrapper" resultMap="infoWrapperMap" parameterType="java.util.Map">
 		SELECT 
 		<include refid="Base_Column_List"/>
-		FROM doc_info t WHERE 1=1 
+		FROM doc_info t WHERE 1=1
 		<if test="id != null and id != ''">
 				 and t.id = #{id}
 		</if>

+ 1 - 1
nlp-web/src/main/resources/application.yml

@@ -12,7 +12,7 @@ spring:
       charset: UTF-8
       enabled: true
   datasource:       # mybatis 配置,使用druid数据源
-    url: jdbc:mysql://1.1.1.1:3306/med-s?useUnicode=true&characterEncoding=UTF-8
+    url: jdbc:mysql://1.1.1.1:3306/diagbot-app?useUnicode=true&characterEncoding=UTF-8
     username: root
     password: diagbot@20180822
     type: com.alibaba.druid.pool.DruidDataSource

+ 7 - 0
nlp/src/main/java/org/diagbot/nlp/feature/FeatureAnalyze.java

@@ -18,6 +18,7 @@ import java.util.Map;
 
 public class FeatureAnalyze {
     private LexemePath<Lexeme> lexemePath = null;
+/*    private String featureNum = "";//特征提取范围*/
 
     Logger logger = LoggerFactory.getLogger(FeatureAnalyze.class);
 
@@ -61,6 +62,7 @@ public class FeatureAnalyze {
 //        }
 //        logger.info("分词文本结果:" + lexeme_text);
         lexemePath = replaceLexeme(lexemePath);
+        /*caseToken.getFeatureSize(featureNum);*/
         return caseToken.analyze(lexemePath);
     }
 
@@ -98,4 +100,9 @@ public class FeatureAnalyze {
         }
         return lexemePath;
     }
+
+  /*  public String setFeatureNum(String featureNum){
+        this.featureNum = featureNum;
+        return featureNum;
+    }*/
 }

+ 31 - 2
nlp/src/main/java/org/diagbot/nlp/feature/extract/CaseToken.java

@@ -6,8 +6,10 @@ import org.diagbot.nlp.util.Constants;
 import org.diagbot.nlp.util.NegativeEnum;
 import org.diagbot.nlp.util.NlpUtil;
 
-import java.util.*;
-
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 public abstract class CaseToken {
     protected static String[] ignore_symbol = new String[]{"、", "."};
     protected static String[] stop_symbol = new String[]{"。", ";", "?", ";", "?", "“", "”", "\r", "\n", "[", "]", "{", "}"};
@@ -20,6 +22,7 @@ public abstract class CaseToken {
     protected Lexeme leftFeatureLexeme = null;
     protected Lexeme rightFeatureLexeme = null;
     protected int sn = 0;
+/*    protected String featureSize = "";*/
 
     static {
         Arrays.sort(ignore_symbol);
@@ -100,6 +103,29 @@ public abstract class CaseToken {
             }
         }
         if (!hasFeature) {
+ /*           if (StringUtils.isNotEmpty(featureSize)) {
+                if(featureSize.equals("all")){//featureSize为all时提取所有特征
+                    Map<String, Object> fMap = new HashMap<>(10);
+                    fMap.put("feature_name", lexeme.getText());
+                    fMap.put("feature_type", featureType);
+                    fMap.put("negative", key);
+                    fMap.put("sn", String.valueOf(sn++));
+                    fMap.put("property", lexeme.getProperty());
+                    fMap.put("concept", lexeme.getConcept());
+                    featuresList.add(fMap);
+                }else {
+                    if (sn < Integer.parseInt(featureSize)){
+                        Map<String, Object> fMap = new HashMap<>(10);
+                        fMap.put("feature_name", lexeme.getText());
+                        fMap.put("feature_type", featureType);
+                        fMap.put("negative", key);
+                        fMap.put("sn", String.valueOf(sn++));
+                        fMap.put("property", lexeme.getProperty());
+                        fMap.put("concept", lexeme.getConcept());
+                        featuresList.add(fMap);
+                    }
+                }
+            }*/
             Map<String, Object> fMap = new HashMap<>(10);
             fMap.put("feature_name", lexeme.getText());
             fMap.put("feature_type", featureType);
@@ -110,5 +136,8 @@ public abstract class CaseToken {
             featuresList.add(fMap);
         }
     }
+  /*  public void getFeatureSize(String fetureSize){
+        this.featureSize = fetureSize;
+    }*/
 }
 

+ 33 - 15
nlp/src/main/java/org/diagbot/nlp/participle/ParticipleUtil.java

@@ -23,20 +23,7 @@ public class ParticipleUtil {
         LexemePath<Lexeme> lexemes = participle(content);
         if (isCombineUnit) {
             ParticipleUtil util = new ParticipleUtil();
-            lexemes = util.combineValidate(lexemes);
-            lexemes = util.joinTime(lexemes);
-
-            String year_pattern = "([1-2][0-9]{3}|[0-9]{2})";
-            String mouth_day_pattern = "([0-9]{2}|[0-9])";
-            String join_pattern = "([-/.]?)";
-            String pattern_string = year_pattern + join_pattern + mouth_day_pattern + join_pattern + mouth_day_pattern;
-            for (Lexeme l : lexemes) {
-                if (l.getProperty().equals(Constants.word_property_number)) {
-                    if (Pattern.matches(pattern_string,l.getText())) {
-                        l.setProperty(Constants.word_property_time);
-                    }
-                }
-            }
+            lexemes = util.combine(util, lexemes);
         }
         return lexemes;
     }
@@ -48,6 +35,19 @@ public class ParticipleUtil {
         return participle(content, NlpCache.segment_cache);
     }
 
+    public static LexemePath<Lexeme> participlePacs(String content) throws IOException {
+        if (NlpCache.segment_cache_pacs == null) {
+            NlpCache.createSegmentCachePacs();
+        }
+        ParticipleToken token = new ParticipleToken();
+        token.start(new StringReader(content), NlpCache.segment_cache_pacs);
+        LexemePath<Lexeme> lexemePath = token.getLexemePath();
+        ParticipleUtil util = new ParticipleUtil();
+        lexemePath = util.combine(util, lexemePath);
+        token.end();
+        return lexemePath;
+    }
+
     public static LexemePath<Lexeme> participle(String content, String path) throws IOException {
         Configuration configuration = new DefaultConfig();
         NlpCache.segment_cache = configuration.loadMainDict(path);
@@ -65,6 +65,24 @@ public class ParticipleUtil {
         return lexemePath;
     }
 
+    private LexemePath<Lexeme> combine(ParticipleUtil util, LexemePath<Lexeme> lexemes) {
+        lexemes = util.combineValidate(lexemes);
+        lexemes = util.joinTime(lexemes);
+
+        String year_pattern = "([1-2][0-9]{3}|[0-9]{2})";
+        String mouth_day_pattern = "([0-9]{2}|[0-9])";
+        String join_pattern = "([-/.]?)";
+        String pattern_string = year_pattern + join_pattern + mouth_day_pattern + join_pattern + mouth_day_pattern;
+        for (Lexeme l : lexemes) {
+            if (l.getProperty().equals(Constants.word_property_number)) {
+                if (Pattern.matches(pattern_string,l.getText())) {
+                    l.setProperty(Constants.word_property_time);
+                }
+            }
+        }
+        return lexemes;
+    }
+
     public static String participleAndHighlight(String content) throws IOException {
         LexemePath<Lexeme> lexemePath = participle(content, false);
         String separator = "&nbsp;*&nbsp;";
@@ -110,7 +128,7 @@ public class ParticipleUtil {
         System.out.println(Pattern.matches(pattern_string,"12.434"));
         try {
             ParticipleUtil util = new ParticipleUtil();
-            String content = "2017-01,9毫克7斤重量015年6月23日出现";
+            String content = "5天2017-01,9毫克7斤重量015年6月23日出现";
             LexemePath<Lexeme> lexemes = util.participle(content);
 
             lexemes = util.combineValidate(lexemes);

+ 14 - 0
nlp/src/main/java/org/diagbot/nlp/util/NlpCache.java

@@ -16,6 +16,8 @@ import java.util.*;
 public class NlpCache {
     //词典库
     public static Segment segment_cache = null;
+    //词典库
+    public static Segment segment_cache_pacs = null;
     //推送字典
     public static Map<String, String> standard_info_push_map = null;
     //词库同义词定义
@@ -34,6 +36,11 @@ public class NlpCache {
         segment_cache = configuration.loadMainDict( "tc.dict");
     }
 
+    public static void createSegmentCachePacs() {
+        Configuration configuration = new DefaultConfig();
+        segment_cache_pacs = configuration.loadMainDict("pacs-tc.dict");
+    }
+
     public static void createPushCache() {
         Configuration configuration = new DefaultConfig();
         standard_info_push_map = configuration.loadMapDict( "push-tc.dict");
@@ -120,6 +127,13 @@ public class NlpCache {
         return segment_cache;
     }
 
+    public static Segment getSegment_cache_pacs() {
+        if (segment_cache_pacs == null) {
+            createSegmentCachePacs();
+        }
+        return segment_cache_pacs;
+    }
+
     public static Map<String, String> getStandard_info_push_map() {
         if (standard_info_push_map == null) {
             createPushCache();

+ 4 - 1
nlp/src/main/resources/nlp.properties

@@ -1,3 +1,6 @@
 #数据文件存放路径
 cache.file.dir=/opt/diagbot-push/cache_file/
-#cache.file.dir=d:\\cache_file\\
+#cache.file.dir=e:\\cache_file\\
+
+#特征提取范围(不限制范围时配置:all)
+#push.feature.num=all

+ 14 - 2
push-web/src/main/java/org/diagbot/push/controller/AlgorithmController.java

@@ -155,19 +155,31 @@ public class AlgorithmController extends BaseController {
         ResponseData graphResponseData = graphCalculate.calculate(request, searchData);
         if (graphResponseData.getDis().size() > 0) {
             List<FeatureRate> disFeatureRates = new ArrayList<>();
-            boolean isFind = false;
+            /*boolean isFind = false;
             for (int i = 0; i < bigDataResponseData.getDis().size(); i++) {
                 FeatureRate bigdata_fr = bigDataResponseData.getDis().get(i);
                 isFind = false;
                 for (FeatureRate graph_fr : graphResponseData.getDis()) {
-                    if (bigdata_fr.getFeatureName().equals(graph_fr.getFeatureName())) {
+                    if (graph_fr.getDesc().contains("拟诊")|| graph_fr.getDesc().contains("确诊") && bigdata_fr.getFeatureName().equals(graph_fr.getFeatureName())) {
                         isFind = true;
                     }
                 }
                 if (!isFind) {
                     disFeatureRates.add(bigdata_fr);
                 }
+            }*/
+            List<FeatureRate> bigdis = bigDataResponseData.getDis();
+            List<FeatureRate> graphdis = graphResponseData.getDis();
+            for (FeatureRate bg:graphdis) {
+                Iterator<FeatureRate> iterator = bigdis.iterator();
+                while (iterator.hasNext()){
+                    FeatureRate gd = iterator.next();
+                    if(gd.getFeatureName().equals(bg.getFeatureName()) &&(bg.getDesc().contains("确诊")|| bg.getDesc().contains("拟诊"))){
+                        iterator.remove();
+                    }
+                }
             }
+            disFeatureRates = bigdis;
             List<FeatureRate> graphFeatureRates = graphResponseData.getDis();
             graphFeatureRates.addAll(disFeatureRates);
             bigDataResponseData.setDis(graphFeatureRates);

+ 2 - 0
push-web/src/main/java/org/diagbot/push/controller/CacheFileManagerController.java

@@ -32,6 +32,7 @@ public class CacheFileManagerController extends BaseController {
         NlpCache.createClassifyCache();
         NlpCache.createChronicCache();
         NlpCache.createSynonymCache();
+        NlpCache.createSegmentCachePacs();
         //更新图谱缓存
         CacheUtil.createDiagSortCache();
         CacheUtil.createSexAgeCache();
@@ -44,6 +45,7 @@ public class CacheFileManagerController extends BaseController {
         ApplicationCacheUtil.createDoc_result_mapping_filter_map();
         ApplicationCacheUtil.create_kl_rule_filter_map();
         ApplicationCacheUtil.create_kl_rule_app_filter_map();
+        ApplicationCacheUtil.create_kl_diagnose_detail_filter_map();
         return response;
     }
 }

+ 11 - 0
push-web/src/main/java/org/diagbot/push/controller/ParticipleController.java

@@ -20,6 +20,17 @@ public class ParticipleController extends BaseController {
         return listView;
     }
 
+    @ResponseBody
+    @RequestMapping("/split_pacs")
+    public Response split(String content) throws IOException {
+        Response response = new Response();
+        long start = System.currentTimeMillis();
+        response.setData(ParticipleUtil.participlePacs(content));
+        long end = System.currentTimeMillis();
+        System.out.println("总耗时:........." + (end - start));
+        return response;
+    }
+
     @ResponseBody
     @RequestMapping("/split_and_highlight")
     public Response splitAndHighlight(String content) throws IOException {

+ 22 - 0
rule/src/main/java/org/diagbot/rule/crisis/CrisisApplication.java

@@ -1,6 +1,7 @@
 package org.diagbot.rule.crisis;
 
 import org.diagbot.common.push.bean.CrisisDetail;
+import org.diagbot.common.push.bean.PreResult;
 import org.diagbot.common.push.bean.Rule;
 import org.diagbot.common.push.bean.RuleApp;
 import org.diagbot.common.push.bean.SearchData;
@@ -77,4 +78,25 @@ public class CrisisApplication {
         }
         return crisisMap;
     }
+
+    private String mergeStandardText(Rule rule) {
+        //标准值最优先匹配
+        StringBuffer sb = new StringBuffer();
+        if (org.apache.commons.lang3.StringUtils.isNotEmpty(rule.getEq_value())) {
+            sb.append(rule.getPub_name()).append(rule.getEq_operator()).append(rule.getEq_value());
+        } else if (org.apache.commons.lang3.StringUtils.isNotEmpty(rule.getMax_value()) && org.apache.commons.lang3.StringUtils.isNotEmpty(rule.getMin_value())) {
+            sb.append(rule.getPub_name()).append(rule.getMin_operator()).append(rule.getMin_value())
+                    .append(rule.getMin_unit()).append(";")
+                    .append(rule.getPub_name()).append(rule.getMax_operator()).append(rule.getMax_value())
+                    .append(rule.getMax_unit());
+        } else if (org.apache.commons.lang3.StringUtils.isNotEmpty(rule.getMin_value())) {
+            sb.append(rule.getPub_name()).append(rule.getMin_operator()).append(rule.getMin_value())
+                    .append(rule.getMin_unit());
+        } else if (org.apache.commons.lang3.StringUtils.isNotEmpty(rule.getMax_value())) {
+            sb.append(rule.getPub_name()).append(rule.getMax_operator()).append(rule.getMax_value())
+                    .append(rule.getMax_unit());
+        }
+        return sb.toString();
+    }
+
 }