From b3631ab1a09f3dd95dd22fc6eedaee14c779f735 Mon Sep 17 00:00:00 2001 From: jenzur Date: Sat, 16 Mar 2019 23:02:52 +0100 Subject: [PATCH] since server area is gone it fetches some messages from hlstats now, will increase amount later, only potentially issue left is a nullpointer in getresponsemsg if none within 8 is reached, removed pipelines with annotation caching, --- .../java/DataLayer/DBCPDataSourceHLstats.java | 42 ++ .../src/main/java/DataLayer/DataMapper.java | 19 +- .../FunctionLayer/LevenshteinDistance.java | 20 +- .../java/FunctionLayer/MYSQLDatahandler.java | 208 ++++-- .../java/FunctionLayer/SimilarityMatrix.java | 43 -- .../StanfordParser/SentimentAnalyzerTest.java | 693 +++++++++--------- .../PresentationLayer/DiscordHandler.java | 16 +- .../target/ArtificialAutism-1.0.jar | Bin 37287 -> 39904 bytes 8 files changed, 559 insertions(+), 482 deletions(-) create mode 100644 ArtificialAutism/src/main/java/DataLayer/DBCPDataSourceHLstats.java diff --git a/ArtificialAutism/src/main/java/DataLayer/DBCPDataSourceHLstats.java b/ArtificialAutism/src/main/java/DataLayer/DBCPDataSourceHLstats.java new file mode 100644 index 00000000..ba9a61f1 --- /dev/null +++ b/ArtificialAutism/src/main/java/DataLayer/DBCPDataSourceHLstats.java @@ -0,0 +1,42 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package DataLayer; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apache.commons.dbcp2.BasicDataSource; + +/** + * + * @author install1 + */ +public class DBCPDataSourceHLstats { + + private static BasicDataSource ds = new BasicDataSource(); + static { + try { + ds.setDriver(new com.mysql.cj.jdbc.Driver()); + ds.setUrl("jdbc:mysql://151.80.230.149:3306/unloze_stats?useLegacyDatetimeCode=false&serverTimezone=UTC"); + ds.setUsername("unloze_stats"); + ds.setPassword("R8J8E9Fzmcc7ZfDAGAk7"); + ds.setMaxTotal(-1); + ds.setMinIdle(5); + ds.setMaxIdle(-1); + ds.setMaxOpenPreparedStatements(100); + } catch (SQLException ex) { + Logger.getLogger(DBCPDataSource.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public static Connection getConnection() throws SQLException { + return ds.getConnection(); + } + + private DBCPDataSourceHLstats() { + } +} diff --git a/ArtificialAutism/src/main/java/DataLayer/DataMapper.java b/ArtificialAutism/src/main/java/DataLayer/DataMapper.java index bab5eab6..824e4e92 100644 --- a/ArtificialAutism/src/main/java/DataLayer/DataMapper.java +++ b/ArtificialAutism/src/main/java/DataLayer/DataMapper.java @@ -179,6 +179,24 @@ public class DataMapper { return LHMSMX; } + public static ConcurrentMap getHLstatsMessages() { + ConcurrentMap hlStatsMessages = new MapMaker().concurrencyLevel(2).makeMap(); + try (Connection l_cCon = DBCPDataSourceHLstats.getConnection()) { + String l_sSQL = "SELECT message FROM `hlstats_Events_Chat`"; + try (PreparedStatement l_pStatement = l_cCon.prepareStatement(l_sSQL, java.sql.ResultSet.TYPE_FORWARD_ONLY, + java.sql.ResultSet.CONCUR_READ_ONLY)) { + try (ResultSet l_rsSearch = l_pStatement.executeQuery()) { + while (l_rsSearch.next()) { + hlStatsMessages.put(hlStatsMessages.size() + 1, l_rsSearch.getString(1)); + } + } + } + } catch (SQLException ex) { + Logger.getLogger(DataMapper.class.getName()).log(Level.SEVERE, null, ex); + } + return hlStatsMessages; + } + public static void CloseConnections(PreparedStatement ps, ResultSet rs, Connection con) { if (rs != null) { try { @@ -202,5 +220,4 @@ public class DataMapper { } } } - } diff --git a/ArtificialAutism/src/main/java/FunctionLayer/LevenshteinDistance.java b/ArtificialAutism/src/main/java/FunctionLayer/LevenshteinDistance.java index 4134e710..b4351d58 100644 --- a/ArtificialAutism/src/main/java/FunctionLayer/LevenshteinDistance.java +++ b/ArtificialAutism/src/main/java/FunctionLayer/LevenshteinDistance.java @@ -5,28 +5,23 @@ */ package FunctionLayer; +import java.util.Map; import java.util.concurrent.Callable; /** * * @author install1 */ -public class LevenshteinDistance implements Callable { +public class LevenshteinDistance implements Callable> { private CharSequence lhs; private CharSequence rhs; - private DistanceObject dco; + private Map.Entry distanceEntry; private static int minimum(int a, int b, int c) { return Math.min(Math.min(a, b), c); } - public LevenshteinDistance(CharSequence lhs, CharSequence rhs, DistanceObject dco) { - this.lhs = lhs; - this.rhs = rhs; - this.dco = dco; - } - public LevenshteinDistance(CharSequence lhs, CharSequence rhs) { this.lhs = lhs; this.rhs = rhs; @@ -52,7 +47,7 @@ public class LevenshteinDistance implements Callable { } @Override - public DistanceObject call() { + public Map.Entry call() { try { int[][] distance = new int[lhs.length() + 1][rhs.length() + 1]; @@ -70,12 +65,11 @@ public class LevenshteinDistance implements Callable { distance[i - 1][j - 1] + ((lhs.charAt(i - 1) == rhs.charAt(j - 1)) ? 0 : 1)); } } - dco.setDistance(distance[lhs.length()][rhs.length()]); + distanceEntry.setValue(distance[lhs.length()][rhs.length()]); } catch (Exception ex) { System.out.println("ex msg: " + ex.getMessage() + "\n"); - dco.setDistance(100); - return dco; + return null; } - return dco; + return distanceEntry; } } diff --git a/ArtificialAutism/src/main/java/FunctionLayer/MYSQLDatahandler.java b/ArtificialAutism/src/main/java/FunctionLayer/MYSQLDatahandler.java index 0651c685..e2f0253f 100644 --- a/ArtificialAutism/src/main/java/FunctionLayer/MYSQLDatahandler.java +++ b/ArtificialAutism/src/main/java/FunctionLayer/MYSQLDatahandler.java @@ -17,6 +17,7 @@ import edu.stanford.nlp.ling.TaggedWord; import edu.stanford.nlp.ling.Word; import edu.stanford.nlp.parser.lexparser.LexicalizedParser; import edu.stanford.nlp.parser.shiftreduce.ShiftReduceParser; +import edu.stanford.nlp.pipeline.Annotation; import edu.stanford.nlp.pipeline.StanfordCoreNLP; import edu.stanford.nlp.process.DocumentPreprocessor; import edu.stanford.nlp.tagger.maxent.MaxentTagger; @@ -33,11 +34,9 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.Random; -import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -57,17 +56,20 @@ public class MYSQLDatahandler { private volatile boolean refreshMatrixFromDB; private static int secondaryIterator = 0; private final ConcurrentMap stringCache; + private static ConcurrentMap pipelineAnnotationCache; + private static ConcurrentMap pipelineSentimentAnnotationCache; + private static ConcurrentMap jmweAnnotationCache; private LinkedHashMap> lHMSMX = new LinkedHashMap(); private final Stopwatch stopwatch; private final Stopwatch stopwatch1; - private ExecutorService executor; - + private ForkJoinPool executor; private static String shiftReduceParserPath = "edu/stanford/nlp/models/srparser/englishSR.ser.gz"; private static String sentimentModel = "edu/stanford/nlp/models/sentiment/sentiment.ser.gz"; private static String lexParserEnglishRNN = "edu/stanford/nlp/models/lexparser/englishRNN.ser.gz"; private static String taggerPath = "edu/stanford/nlp/models/pos-tagger/english-left3words/english-left3words-distsim.tagger"; private static String nerModel = "edu/stanford/nlp/models/ner/english.all.3class.distsim.crf.ser.gz"; private static String jmweIndexData = "/home/javatests/lib/mweindex_wordnet3.0_semcor1.6.data"; // ./lib/mweindex_wordnet3.0_semcor1.6.data + private static String jmweIndexDataLocalTest = "E:/java8/Projects/mweindex_wordnet3.0_semcor1.6.data"; private static MaxentTagger tagger; private static ShiftReduceParser model; private static String[] options = {"-maxLength", "100"}; @@ -83,27 +85,17 @@ public class MYSQLDatahandler { private static StanfordCoreNLP pipelineSentiment; private static StanfordCoreNLP pipelineJMWE; - public static AbstractSequenceClassifier getClassifier() { - return classifier; - } - - public static void setClassifier(AbstractSequenceClassifier classifier) { - MYSQLDatahandler.classifier = classifier; - } - - public void instantiateExecutor() { - this.executor = new ForkJoinPool(Runtime.getRuntime().availableProcessors(), - ForkJoinPool.defaultForkJoinWorkerThreadFactory, - null, true); - } - public MYSQLDatahandler() { this.stopwatch = Stopwatch.createUnstarted(); this.stopwatch1 = Stopwatch.createStarted(); this.stringCache = new MapMaker().concurrencyLevel(2).makeMap(); + //cant sadly just have one annotation for every pipelines, one pipeline per annotation is required + this.jmweAnnotationCache = new MapMaker().concurrencyLevel(2).makeMap(); + this.pipelineAnnotationCache = new MapMaker().concurrencyLevel(2).makeMap(); + this.pipelineSentimentAnnotationCache = new MapMaker().concurrencyLevel(2).makeMap(); } - public static void shiftReduceParserInitiate() { + public void shiftReduceParserInitiate() { try { classifier = CRFClassifier.getClassifierNoExceptions(nerModel); } catch (ClassCastException ex) { @@ -127,7 +119,7 @@ public class MYSQLDatahandler { propsJMWE.setProperty("customAnnotatorClass.jmwe", "edu.stanford.nlp.pipeline.JMWEAnnotator"); propsJMWE.setProperty("customAnnotatorClass.jmwe.verbose", "false"); propsJMWE.setProperty("customAnnotatorClass.jmwe.underscoreReplacement", "-"); - propsJMWE.setProperty("customAnnotatorClass.jmwe.indexData", jmweIndexData); + propsJMWE.setProperty("customAnnotatorClass.jmwe.indexData", jmweIndexData); //jmweIndexDataLocalTest jmweIndexData propsJMWE.setProperty("customAnnotatorClass.jmwe.detector", "Exhaustive"); //"Consecutive", "Exhaustive", "ProperNouns", "Complex" and "CompositeConsecutiveProperNouns" propsJMWE.setProperty("annotators", "tokenize, ssplit, pos, lemma, jmwe"); @@ -137,8 +129,26 @@ public class MYSQLDatahandler { pipelineJMWE = new StanfordCoreNLP(propsJMWE); } - public static StanfordCoreNLP getPipelineJMWE() { - return pipelineJMWE; + public static AbstractSequenceClassifier getClassifier() { + return classifier; + } + + public static void setClassifier(AbstractSequenceClassifier classifier) { + MYSQLDatahandler.classifier = classifier; + } + + public void updateStringCache() { + try { + checkIfUpdateStrings(); + } catch (CustomError ex) { + Logger.getLogger(MYSQLDatahandler.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public void instantiateExecutor() { + this.executor = new ForkJoinPool(Runtime.getRuntime().availableProcessors(), + ForkJoinPool.defaultForkJoinWorkerThreadFactory, + null, false); //true } public static GrammaticalStructureFactory getGsf() { @@ -177,6 +187,7 @@ public class MYSQLDatahandler { try { DataMapper.createTables(); stringCache.putAll(getCache()); + addHLstatsMessages(); lHMSMX = DataMapper.getAllRelationScores(); } catch (CustomError ex) { Logger.getLogger(MYSQLDatahandler.class @@ -184,6 +195,52 @@ public class MYSQLDatahandler { } } + private void addHLstatsMessages() { + ConcurrentMap hlStatsMessages = DataMapper.getHLstatsMessages(); + ConcurrentMap strCacheLocal = stringCache; + int hardcap = 300; + int counter = 0; + for (String str : hlStatsMessages.values()) { + if (!str.startsWith("!")) { + boolean present = false; + for (String str1 : strCacheLocal.values()) { + if (str.equals(str1)) { + present = true; + break; + } + } + if (!present) { + MessageResponseHandler.getMessage(str); + } + } + if (counter >= hardcap) { + break; + } + counter++; + } + } + + public void instantiateAnnotationMap() { + for (String str : stringCache.values()) { + System.out.println("str annotation jmwe: " + str + "\n"); + Annotation strAnno = new Annotation(str); + pipelineJMWE.annotate(strAnno); + jmweAnnotationCache.put(str, strAnno); + } + for (String str : stringCache.values()) { + System.out.println("str annotation pipeline: " + str + "\n"); + Annotation strAnno = new Annotation(str); + pipeline.annotate(strAnno); + pipelineAnnotationCache.put(str, strAnno); + } + for (String str : stringCache.values()) { + System.out.println("str annotation pipelinesentiment: " + str + "\n"); + Annotation strAnno = new Annotation(str); + pipelineSentiment.annotate(strAnno); + pipelineSentimentAnnotationCache.put(str, strAnno); + } + } + public synchronized void checkIfUpdateMatrixes() { refreshMatrixFromDB = false; int counter = 0; @@ -233,47 +290,52 @@ public class MYSQLDatahandler { boolean present = false; LinkedHashMap orDefault = lHMSMX.getOrDefault(str, null); if (orDefault != null) { - Double orDefault1 = orDefault.getOrDefault(str1, null); - if (orDefault1 != null) { - // System.out.println("present true \nstr: " + str + "\nstr1: " + str1 + "\n"); - present = true; + for (String strkey : orDefault.keySet()) { + if (strkey.equals(str1)) { + present = true; + break; + } } } if (!present) { orDefault = lHMSMX.getOrDefault(str1, null); if (orDefault != null) { - Double orDefault1 = orDefault.getOrDefault(str, null); - if (orDefault1 != null) { - // System.out.println("present true \nstr: " + str + "\nstr1: " + str1 + "\n"); - present = true; + for (String strkey : orDefault.keySet()) { + if (strkey.equals(str)) { + present = true; + break; + } } } } if (!present) { - SimilarityMatrix SMX = new SimilarityMatrix(str, str1); - Callable worker = new SentimentAnalyzerTest(str, str1, SMX); - futures.put(futures.size() + 1, executor.submit(worker)); LinkedHashMap orDefault1 = lHMSMX.getOrDefault(str, null); if (orDefault1 == null) { orDefault1 = new LinkedHashMap(); } orDefault1.put(str1, 0.0); lHMSMX.put(str, orDefault1); + SimilarityMatrix SMX = new SimilarityMatrix(str, str1); + Callable worker = new SentimentAnalyzerTest(str, str1, SMX, jmweAnnotationCache.get(str), + jmweAnnotationCache.get(str1), pipelineAnnotationCache.get(str), pipelineAnnotationCache.get(str1), + pipelineSentimentAnnotationCache.get(str), pipelineSentimentAnnotationCache.get(str1)); + futures.put(futures.size() + 1, executor.submit(worker)); } }); }); System.out.println("finished worker assignment, futures size: " + futures.size() + "\n"); for (Future future : futures.values()) { - System.out.println("counter: " + counter + "\n"); - counter++; SimilarityMatrix SMX = new SimilarityMatrix("", ""); try { SMX = future.get(20, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException ex) { Logger.getLogger(MYSQLDatahandler.class.getName()).log(Level.SEVERE, null, ex); + SMX = null; } - LinkedHashMap getFuture = lHMSMX.getOrDefault(SMX.getPrimaryString(), null); - if (getFuture != null) { + System.out.println("counter: " + counter + "\nSMX: " + SMX == null ? "SMX null\n" : "SMX not null\n"); + counter++; + if (SMX != null) { + LinkedHashMap getFuture = lHMSMX.getOrDefault(SMX.getPrimaryString(), null); getFuture.put(SMX.getSecondaryString(), SMX.getDistance()); lHMSMX.put(SMX.getPrimaryString(), getFuture); matrixUpdateList.put(matrixUpdateList.size() + 1, SMX); @@ -309,6 +371,15 @@ public class MYSQLDatahandler { for (String str1 : str.values()) { stringCache.put(j, str1); j++; + Annotation strAnno = new Annotation(str1); + pipelineJMWE.annotate(strAnno); + jmweAnnotationCache.put(str1, strAnno); + strAnno = new Annotation(str1); + pipeline.annotate(strAnno); + pipelineAnnotationCache.put(str1, strAnno); + strAnno = new Annotation(str1); + pipelineSentiment.annotate(strAnno); + pipelineSentimentAnnotationCache.put(str1, strAnno); } if (!stopwatch.isRunning()) { stopwatch.start(); @@ -329,7 +400,7 @@ public class MYSQLDatahandler { SimilarityMatrix SMXreturn = new SimilarityMatrix("", ""); System.out.println("pre mostSimilarSTR \n"); String mostSimilarSTR = mostSimilar(str, strArrs); - if (mostSimilarSTR != null && !mostSimilarSTR.isEmpty()) { + if (mostSimilarSTR != null) { System.out.println("mostSimilarSTR; " + mostSimilarSTR + "\n"); LinkedHashMap orDefault = LHMSMXLocal.getOrDefault(mostSimilarSTR, null); if (orDefault != null) { @@ -366,14 +437,24 @@ public class MYSQLDatahandler { ConcurrentMap> futureslocal = new MapMaker().concurrencyLevel(2).makeMap(); for (String str1 : strCache.values()) { if (!str.equals(str1)) { - Callable worker = new SentimentAnalyzerTest(str, str1, new SimilarityMatrix(str, str1)); + SimilarityMatrix SMX = new SimilarityMatrix(str, str1); + Callable worker = new SentimentAnalyzerTest(str, str1, SMX, + jmweAnnotationCache.get(str), jmweAnnotationCache.get(str1), pipelineAnnotationCache.get(str), + pipelineAnnotationCache.get(str1), pipelineSentimentAnnotationCache.get(str), + pipelineSentimentAnnotationCache.get(str1)); futureslocal.put(futureslocal.size() + 1, executor.submit(worker)); } } int index = 0; for (Future future : futureslocal.values()) { + SimilarityMatrix SMX = new SimilarityMatrix("", ""); try { - SimilarityMatrix SMX = future.get((long) 20, TimeUnit.SECONDS); + SMX = future.get(20, TimeUnit.SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException ex) { + System.out.println("ex getResponsemsg: " + ex.getMessage() + "\n"); + SMX = null; + } + if (SMX != null) { double distance = SMX.getDistance(); System.out.println("index: " + index + "\nfutures size: " + futureslocal.values().size() + "\nScore: " + SMX.getDistance() + "\nSecondary: " + SMX.getSecondaryString() + "\nPrimary: " + SMX.getPrimaryString() + "\n"); @@ -381,8 +462,6 @@ public class MYSQLDatahandler { Score = distance; SMXreturn = SMX; } - } catch (InterruptedException | ExecutionException | TimeoutException ex) { - System.out.println("ex: " + ex.getMessage() + "\n"); } index++; } @@ -394,18 +473,19 @@ public class MYSQLDatahandler { public String mostSimilar(String toBeCompared, ConcurrentMap concurrentStrings) { int minDistance = 8; String similar = ""; - ConcurrentMap> futures = new MapMaker().concurrencyLevel(2).makeMap(); - concurrentStrings.values().stream().map((str) -> new LevenshteinDistance(str, toBeCompared, new DistanceObject())).forEachOrdered((worker) -> { + ConcurrentMap>> futures = new MapMaker().concurrencyLevel(2).makeMap(); + for (String str : concurrentStrings.values()) { + Callable> worker = new LevenshteinDistance(toBeCompared, str); futures.put(futures.size() + 1, executor.submit(worker)); - }); - for (Future future : futures.values()) { + } + for (Future> future : futures.values()) { try { - DistanceObject d = future.get(); - int distance = d.getDistance(); - System.out.println("distance: " + distance + "\n"); + Entry futureEntry = future.get(); + int distance = futureEntry.getValue(); if (distance < minDistance) { + System.out.println("distance: " + distance + "\n"); minDistance = distance; - similar = d.getSentence(); + similar = futureEntry.getKey(); } } catch (NullPointerException | InterruptedException | ExecutionException ex) { System.out.println("failed future\n"); @@ -605,17 +685,10 @@ public class MYSQLDatahandler { ConcurrentMap returnmap = new MapMaker().concurrencyLevel(2).makeMap(); ConcurrentMap allStrings = stringCache; int intervalAprove = allStrings.values().size() / 10; - String str1 = "and to revise the questions and materials and such"; - String str2 = "as William said earlier. Visiting your dentist once or twice a year is enough"; - String str3 = "At least, you have more time to prepare then"; for (String str : strmap.values()) { + int counter = 0; + boolean calculationIssues = false; ConcurrentMap> futures = new MapMaker().concurrencyLevel(2).makeMap(); - Callable worker = new SentimentAnalyzerTest(str, str1, new SimilarityMatrix(str, str1)); - futures.put(futures.size() + 1, executor.submit(worker)); - worker = new SentimentAnalyzerTest(str, str2, new SimilarityMatrix(str, str2)); - futures.put(futures.size() + 1, executor.submit(worker)); - worker = new SentimentAnalyzerTest(str, str3, new SimilarityMatrix(str, str3)); - futures.put(futures.size() + 1, executor.submit(worker)); int ij2 = 0; if (allStrings.isEmpty()) { allStrings = strmap; @@ -624,15 +697,24 @@ public class MYSQLDatahandler { if (ij2 > intervalAprove) { break; } - worker = new SentimentAnalyzerTest(str, strValues, new SimilarityMatrix(str, strValues)); + Callable worker = new SentimentAnalyzerTest(str, strValues, new SimilarityMatrix(str, strValues), + jmweAnnotationCache.get(str), jmweAnnotationCache.get(strValues), pipelineAnnotationCache.get(str), + pipelineAnnotationCache.get(strValues), pipelineSentimentAnnotationCache.get(str), + pipelineSentimentAnnotationCache.get(strValues)); futures.put(futures.size() + 1, executor.submit(worker)); ij2++; } - int counter = 0; - boolean calculationIssues = false; for (Future future : futures.values()) { try { - future.get(20, TimeUnit.SECONDS); + SimilarityMatrix get = future.get(20, TimeUnit.SECONDS); + if (get == null) { + System.out.println("counter timeouts: " + counter + "\n"); + counter++; + if (counter >= 10) { + calculationIssues = true; + break; + } + } } catch (InterruptedException | ExecutionException | TimeoutException ex) { System.out.println("counter timeouts: " + counter + "\n"); counter++; diff --git a/ArtificialAutism/src/main/java/FunctionLayer/SimilarityMatrix.java b/ArtificialAutism/src/main/java/FunctionLayer/SimilarityMatrix.java index 9991b162..1445a0e4 100644 --- a/ArtificialAutism/src/main/java/FunctionLayer/SimilarityMatrix.java +++ b/ArtificialAutism/src/main/java/FunctionLayer/SimilarityMatrix.java @@ -41,49 +41,6 @@ public class SimilarityMatrix{ this.distance = result; } - /* - public double getDistanceCalculations() { - ILexicalDatabase db = new NictWordNet(); - WS4JConfiguration.getInstance().setMFS(true); - RelatednessCalculator rc1 = new WuPalmer(db); - RelatednessCalculator rc2 = new Resnik(db); - RelatednessCalculator rc3 = new JiangConrath(db); - RelatednessCalculator rc4 = new Lin(db); - RelatednessCalculator rc5 = new LeacockChodorow(db); - RelatednessCalculator rc6 = new Path(db); - RelatednessCalculator rc7 = new Lesk(db); - RelatednessCalculator rc8 = new HirstStOnge(db); - double maxScore = -1D; - List RCList = new ArrayList(); - RCList.add(rc1); - RCList.add(rc2); - RCList.add(rc3); - RCList.add(rc4); - RCList.add(rc5); - RCList.add(rc6); - RCList.add(rc7); - RCList.add(rc8); - for (RelatednessCalculator rc : RCList) { - double s = rc.calcRelatednessOfWords(PrimaryString, SecondaryString); - s /= 1000; - if (s > 0.000000) { - System.out.println("s: " + s + "\n" + " PrimaryString: " + PrimaryString + "\n" + " SecondaryString: " + SecondaryString + "\n" - + " rc: " + rc.toString() + "\n"); - } - String str = String.format("%.12f", s); - if (str.contains(",")) { - str = str.substring(0, str.indexOf(",")); - } - int strend = str.length() > 6 ? 6 : str.length(); - str = str.substring(0, strend); - double score = Double.valueOf(str); - if (score > maxScore) { - maxScore = score; - } - } - return maxScore == -1D ? 0.00 : maxScore; - } - */ public String getPrimaryString() { return PrimaryString; } diff --git a/ArtificialAutism/src/main/java/FunctionLayer/StanfordParser/SentimentAnalyzerTest.java b/ArtificialAutism/src/main/java/FunctionLayer/StanfordParser/SentimentAnalyzerTest.java index 78ae931d..6cde4faa 100644 --- a/ArtificialAutism/src/main/java/FunctionLayer/StanfordParser/SentimentAnalyzerTest.java +++ b/ArtificialAutism/src/main/java/FunctionLayer/StanfordParser/SentimentAnalyzerTest.java @@ -53,7 +53,6 @@ import org.ejml.simple.SimpleMatrix; public class SentimentAnalyzerTest implements Callable { private SimilarityMatrix smxParam; - private String str; private String str1; private ShiftReduceParser model; @@ -61,372 +60,364 @@ public class SentimentAnalyzerTest implements Callable { private GrammaticalStructureFactory gsf; private StanfordCoreNLP pipeline; private StanfordCoreNLP pipelineSentiment; - private StanfordCoreNLP pipelineJMWE; private AbstractSequenceClassifier classifier; + private Annotation jmweStrAnnotation1; + private Annotation jmweStrAnnotation2; + private Annotation pipelineAnnotation1; + private Annotation pipelineAnnotation2; + private Annotation pipelineAnnotation1Sentiment; + private Annotation pipelineAnnotation2Sentiment; - public SentimentAnalyzerTest(String str, String str1, SimilarityMatrix smxParam) { + public SentimentAnalyzerTest(String str, String str1, SimilarityMatrix smxParam, Annotation str1Annotation, Annotation str2Annotation, + Annotation strPipeline1, Annotation strPipeline2, Annotation strPipeSentiment1, Annotation strPipeSentiment2) { this.str = str; this.str1 = str1; this.smxParam = smxParam; - model = MYSQLDatahandler.getModel(); - tagger = MYSQLDatahandler.getTagger(); - pipeline = MYSQLDatahandler.getPipeline(); - pipelineSentiment = MYSQLDatahandler.getPipelineSentiment(); - pipelineJMWE = MYSQLDatahandler.getPipelineJMWE(); - gsf = MYSQLDatahandler.getGsf(); - classifier = MYSQLDatahandler.getClassifier(); + this.model = MYSQLDatahandler.getModel(); + this.tagger = MYSQLDatahandler.getTagger(); + this.pipeline = MYSQLDatahandler.getPipeline(); + this.pipelineSentiment = MYSQLDatahandler.getPipelineSentiment(); + this.gsf = MYSQLDatahandler.getGsf(); + this.classifier = MYSQLDatahandler.getClassifier(); + this.jmweStrAnnotation1 = str1Annotation; + this.jmweStrAnnotation2 = str2Annotation; + this.pipelineAnnotation1 = strPipeline1; + this.pipelineAnnotation2 = strPipeline2; + this.pipelineAnnotation1Sentiment = strPipeSentiment1; //maybe process? + this.pipelineAnnotation2Sentiment = strPipeSentiment2; } @Override public SimilarityMatrix call() { - try { - Double score = -100.0; - List> taggedwordlist1 = new ArrayList(); - List> taggedwordlist2 = new ArrayList(); - DocumentPreprocessor tokenizer = new DocumentPreprocessor(new StringReader(str1)); - for (List sentence : tokenizer) { - taggedwordlist1.add(model.apply(tagger.tagSentence(sentence)).taggedYield()); - } - tokenizer = new DocumentPreprocessor(new StringReader(str)); - for (List sentence : tokenizer) { - taggedwordlist2.add(model.apply(tagger.tagSentence(sentence)).taggedYield()); - } - int counter = 0; - int counter1 = 0; - counter = taggedwordlist2.stream().map((taggedlist2) -> taggedlist2.size()).reduce(counter, Integer::sum); - counter1 = taggedwordlist1.stream().map((taggedlist1) -> taggedlist1.size()).reduce(counter1, Integer::sum); - int overValue = counter >= counter1 ? counter - counter1 : counter1 - counter; - overValue *= 16; - score -= overValue; - ConcurrentMap tgwlistIndex = new MapMaker().concurrencyLevel(2).makeMap(); - taggedwordlist1.forEach((TGWList) -> { - TGWList.forEach((TaggedWord) -> { - if (!tgwlistIndex.values().contains(TaggedWord.tag()) && !TaggedWord.tag().equals(":")) { - tgwlistIndex.put(tgwlistIndex.size() + 1, TaggedWord.tag()); - } - }); - }); - taggedwordlist1.clear(); - AtomicInteger runCount = new AtomicInteger(0); - taggedwordlist2.forEach((TGWList) -> { - TGWList.forEach((TaggedWord) -> { - if (tgwlistIndex.values().contains(TaggedWord.tag())) { - tgwlistIndex.values().remove(TaggedWord.tag()); - runCount.getAndIncrement(); - } - }); - }); - tgwlistIndex.clear(); - taggedwordlist2.clear(); - score += runCount.get() * 64; - Annotation annotation = new Annotation(str1); - pipeline.annotate(annotation); - ConcurrentMap sentenceConstituencyParseList = new MapMaker().concurrencyLevel(2).makeMap(); - for (CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class)) { - Tree sentenceConstituencyParse = sentence.get(TreeCoreAnnotations.TreeAnnotation.class); - sentenceConstituencyParseList.put(sentenceConstituencyParseList.size(), sentenceConstituencyParse); - } - Annotation annotation1 = new Annotation(str); - pipeline.annotate(annotation1); - for (CoreMap sentence : annotation1.get(CoreAnnotations.SentencesAnnotation.class)) { - Tree sentenceConstituencyParse = sentence.get(TreeCoreAnnotations.TreeAnnotation.class); - GrammaticalStructure gs = gsf.newGrammaticalStructure(sentenceConstituencyParse); - Collection allTypedDependencies = gs.allTypedDependencies(); - ConcurrentMap filerTreeContent = new MapMaker().concurrencyLevel(2).makeMap(); - for (Tree sentenceConstituencyParse1 : sentenceConstituencyParseList.values()) { - Set inT1notT2 = Tdiff.markDiff(sentenceConstituencyParse, sentenceConstituencyParse1); - Set inT2notT1 = Tdiff.markDiff(sentenceConstituencyParse1, sentenceConstituencyParse); - ConcurrentMap constiLabels = new MapMaker().concurrencyLevel(2).makeMap(); - for (Constituent consti : inT1notT2) { - for (Constituent consti1 : inT2notT1) { - if (consti.value().equals(consti1.value()) && !constiLabels.values().contains(consti.value())) { - score += 64; - constiLabels.put(constiLabels.size(), consti.value()); - } - } - } - GrammaticalStructure gs1 = gsf.newGrammaticalStructure(sentenceConstituencyParse1); - Collection allTypedDependencies1 = gs1.allTypedDependencies(); - for (TypedDependency TDY1 : allTypedDependencies1) { - IndexedWord dep = TDY1.dep(); - IndexedWord gov = TDY1.gov(); - GrammaticalRelation grammaticalRelation = gs.getGrammaticalRelation(gov, dep); - if (grammaticalRelation.isApplicable(sentenceConstituencyParse)) { - score += 900; - } - GrammaticalRelation reln = TDY1.reln(); - if (reln.isApplicable(sentenceConstituencyParse)) { - score += 256; - } - } - for (TypedDependency TDY : allTypedDependencies) { - IndexedWord dep = TDY.dep(); - IndexedWord gov = TDY.gov(); - GrammaticalRelation grammaticalRelation = gs1.getGrammaticalRelation(gov, dep); - if (grammaticalRelation.isApplicable(sentenceConstituencyParse)) { - score += 900; - } - GrammaticalRelation reln = TDY.reln(); - if (reln.isApplicable(sentenceConstituencyParse1)) { - score += 256; - } - } - AtomicInteger runCount1 = new AtomicInteger(0); - sentenceConstituencyParse.taggedLabeledYield().forEach((LBW) -> { - sentenceConstituencyParse1.taggedLabeledYield().stream().filter((LBW1) -> (LBW.lemma().equals(LBW1.lemma()) - && !filerTreeContent.values().contains(LBW.lemma()))).map((_item) -> { - filerTreeContent.put(filerTreeContent.size() + 1, LBW.lemma()); - return _item; - }).forEachOrdered((_item) -> { - runCount1.getAndIncrement(); - }); - }); - score += runCount1.get() * 1500; + Double score = -100.0; + List> taggedwordlist1 = new ArrayList(); + List> taggedwordlist2 = new ArrayList(); + DocumentPreprocessor tokenizer = new DocumentPreprocessor(new StringReader(str1)); + for (List sentence : tokenizer) { + taggedwordlist1.add(model.apply(tagger.tagSentence(sentence)).taggedYield()); + } + tokenizer = new DocumentPreprocessor(new StringReader(str)); + for (List sentence : tokenizer) { + taggedwordlist2.add(model.apply(tagger.tagSentence(sentence)).taggedYield()); + } + int counter = 0; + int counter1 = 0; + counter = taggedwordlist2.stream().map((taggedlist2) -> taggedlist2.size()).reduce(counter, Integer::sum); + counter1 = taggedwordlist1.stream().map((taggedlist1) -> taggedlist1.size()).reduce(counter1, Integer::sum); + int overValue = counter >= counter1 ? counter - counter1 : counter1 - counter; + overValue *= 16; + score -= overValue; + ConcurrentMap tgwlistIndex = new MapMaker().concurrencyLevel(2).makeMap(); + taggedwordlist1.forEach((TGWList) -> { + TGWList.forEach((TaggedWord) -> { + if (!tgwlistIndex.values().contains(TaggedWord.tag()) && !TaggedWord.tag().equals(":")) { + tgwlistIndex.put(tgwlistIndex.size() + 1, TaggedWord.tag()); } - } - sentenceConstituencyParseList.clear(); - Annotation annotationSentiment1 = pipelineSentiment.process(str); - ConcurrentMap simpleSMXlist = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap simpleSMXlistVector = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap sentiment1 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap sentiment2 = new MapMaker().concurrencyLevel(2).makeMap(); - for (CoreMap sentence : annotationSentiment1.get(CoreAnnotations.SentencesAnnotation.class)) { - Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class); - sentiment1.put(sentiment1.size(), RNNCoreAnnotations.getPredictedClass(tree)); - SimpleMatrix predictions = RNNCoreAnnotations.getPredictions(tree); - SimpleMatrix nodeVector = RNNCoreAnnotations.getNodeVector(tree); - simpleSMXlist.put(simpleSMXlist.size(), predictions); - simpleSMXlistVector.put(simpleSMXlistVector.size() + 1, nodeVector); - } - annotationSentiment1 = pipelineSentiment.process(str1); - for (CoreMap sentence : annotationSentiment1.get(CoreAnnotations.SentencesAnnotation.class)) { - Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class); - sentiment2.put(sentiment2.size() + 1, RNNCoreAnnotations.getPredictedClass(tree)); - SimpleMatrix predictions = RNNCoreAnnotations.getPredictions(tree); - SimpleMatrix nodeVector = RNNCoreAnnotations.getNodeVector(tree); - score = simpleSMXlist.values().stream().map((simpleSMX) -> predictions.dot(simpleSMX) * 100).map((dot) -> dot > 50 ? dot - 50 : 50 - dot).map((subtracter) -> { - subtracter *= 25; - return subtracter; - }).map((subtracter) -> subtracter).reduce(score, (accumulator, _item) -> accumulator - _item); - for (SimpleMatrix simpleSMX : simpleSMXlistVector.values()) { - double dot = nodeVector.dot(simpleSMX); - double elementSum = nodeVector.kron(simpleSMX).elementSum(); - elementSum = Math.round(elementSum * 100.0) / 100.0; - if (dot < 0.1) { + }); + }); + taggedwordlist1.clear(); + AtomicInteger runCount = new AtomicInteger(0); + taggedwordlist2.forEach((TGWList) -> { + TGWList.forEach((TaggedWord) -> { + if (tgwlistIndex.values().contains(TaggedWord.tag())) { + tgwlistIndex.values().remove(TaggedWord.tag()); + runCount.getAndIncrement(); + } + }); + }); + tgwlistIndex.clear(); + taggedwordlist2.clear(); + score += runCount.get() * 64; + ConcurrentMap sentenceConstituencyParseList = new MapMaker().concurrencyLevel(2).makeMap(); + for (CoreMap sentence : pipelineAnnotation1.get(CoreAnnotations.SentencesAnnotation.class)) { + Tree sentenceConstituencyParse = sentence.get(TreeCoreAnnotations.TreeAnnotation.class); + sentenceConstituencyParseList.put(sentenceConstituencyParseList.size(), sentenceConstituencyParse); + } + for (CoreMap sentence : pipelineAnnotation2.get(CoreAnnotations.SentencesAnnotation.class)) { + Tree sentenceConstituencyParse = sentence.get(TreeCoreAnnotations.TreeAnnotation.class); + GrammaticalStructure gs = gsf.newGrammaticalStructure(sentenceConstituencyParse); + Collection allTypedDependencies = gs.allTypedDependencies(); + ConcurrentMap filerTreeContent = new MapMaker().concurrencyLevel(2).makeMap(); + for (Tree sentenceConstituencyParse1 : sentenceConstituencyParseList.values()) { + Set inT1notT2 = Tdiff.markDiff(sentenceConstituencyParse, sentenceConstituencyParse1); + Set inT2notT1 = Tdiff.markDiff(sentenceConstituencyParse1, sentenceConstituencyParse); + ConcurrentMap constiLabels = new MapMaker().concurrencyLevel(2).makeMap(); + for (Constituent consti : inT1notT2) { + for (Constituent consti1 : inT2notT1) { + if (consti.value().equals(consti1.value()) && !constiLabels.values().contains(consti.value())) { + score += 64; + constiLabels.put(constiLabels.size(), consti.value()); + } + } + } + GrammaticalStructure gs1 = gsf.newGrammaticalStructure(sentenceConstituencyParse1); + Collection allTypedDependencies1 = gs1.allTypedDependencies(); + for (TypedDependency TDY1 : allTypedDependencies1) { + IndexedWord dep = TDY1.dep(); + IndexedWord gov = TDY1.gov(); + GrammaticalRelation grammaticalRelation = gs.getGrammaticalRelation(gov, dep); + if (grammaticalRelation.isApplicable(sentenceConstituencyParse)) { + score += 900; + } + GrammaticalRelation reln = TDY1.reln(); + if (reln.isApplicable(sentenceConstituencyParse)) { score += 256; } - if (elementSum < 0.1 && elementSum > 0.0) { - score += 1300; - } else if (elementSum > 0.1 && elementSum < 1.0) { - score -= 1100; - } else { - score -= 1424; + } + for (TypedDependency TDY : allTypedDependencies) { + IndexedWord dep = TDY.dep(); + IndexedWord gov = TDY.gov(); + GrammaticalRelation grammaticalRelation = gs1.getGrammaticalRelation(gov, dep); + if (grammaticalRelation.isApplicable(sentenceConstituencyParse)) { + score += 900; + } + GrammaticalRelation reln = TDY.reln(); + if (reln.isApplicable(sentenceConstituencyParse1)) { + score += 256; } } + AtomicInteger runCount1 = new AtomicInteger(0); + sentenceConstituencyParse.taggedLabeledYield().forEach((LBW) -> { + sentenceConstituencyParse1.taggedLabeledYield().stream().filter((LBW1) -> (LBW.lemma().equals(LBW1.lemma()) + && !filerTreeContent.values().contains(LBW.lemma()))).map((_item) -> { + filerTreeContent.put(filerTreeContent.size() + 1, LBW.lemma()); + return _item; + }).forEachOrdered((_item) -> { + runCount1.getAndIncrement(); + }); + }); + score += runCount1.get() * 1500; } - score -= (sentiment1.size() > sentiment2.size() ? sentiment1.size() - sentiment2.size() : sentiment2.size() - sentiment1.size()) * 500; - DocumentReaderAndWriter readerAndWriter = classifier.makePlainTextReaderAndWriter(); - List classifyRaw1 = classifier.classifyRaw(str, readerAndWriter); - List classifyRaw2 = classifier.classifyRaw(str1, readerAndWriter); - score -= (classifyRaw1.size() > classifyRaw2.size() ? classifyRaw1.size() - classifyRaw2.size() : classifyRaw2.size() - classifyRaw1.size()) * 200; - Annotation annotationSentiment = pipelineSentiment.process(str); - int mainSentiment1 = 0; - int longest1 = 0; - int mainSentiment2 = 0; - int longest2 = 0; - for (CoreMap sentence : annotationSentiment.get(CoreAnnotations.SentencesAnnotation.class)) { - Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class); - int sentiment = RNNCoreAnnotations.getPredictedClass(tree); - String partText = sentence.toString(); - SimpleMatrix predictions = RNNCoreAnnotations.getPredictions(tree); - if (partText.length() > longest1) { - mainSentiment1 = sentiment; - longest1 = partText.length(); - } - } - annotationSentiment = pipelineSentiment.process(str1); - for (CoreMap sentence : annotationSentiment.get(CoreAnnotations.SentencesAnnotation.class)) { - Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class); - int sentiment = RNNCoreAnnotations.getPredictedClass(tree); - SimpleMatrix predictions = RNNCoreAnnotations.getPredictions(tree); - String partText = sentence.toString(); - if (partText.length() > longest2) { - mainSentiment2 = sentiment; - longest2 = partText.length(); - } - } - if (longest1 != longest2) { - long deffLongest = longest1 > longest2 ? longest1 : longest2; - long deffshorter = longest1 < longest2 ? longest1 : longest2; - if (deffLongest >= (deffshorter * 2) - 1 && deffLongest - deffshorter <= 45) { - score += (deffLongest - deffshorter) * 200; - } else if (mainSentiment1 != mainSentiment2 && deffLongest - deffshorter > 20 && deffLongest - deffshorter < 45) { - score += (deffLongest - deffshorter) * 200; - } else { - score -= (deffLongest - deffshorter) * 50; - } - } - Annotation jmweStrAnnotation = new Annotation(str); - pipelineJMWE.annotate(jmweStrAnnotation); - List sentences = jmweStrAnnotation.get(CoreAnnotations.SentencesAnnotation.class); - int tokensCounter1 = 0; - int tokensCounter2 = 0; - int anotatorcounter1 = 0; - int anotatorcounter2 = 0; - int inflectedCounterPositive1 = 0; - int inflectedCounterPositive2 = 0; - int inflectedCounterNegative = 0; - int MarkedContinuousCounter1 = 0; - int MarkedContinuousCounter2 = 0; - int UnmarkedPatternCounter = 0; - ConcurrentMap ITokenMapTag1 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap ITokenMapTag2 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap strTokenStems1 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap strTokenStems2 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap strTokenForm1 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap strTokenForm2 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap strTokenGetEntry1 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap strTokenGetEntry2 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap strTokenGetiPart1 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap strTokenGetiPart2 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap strTokenEntryPOS1 = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap strTokenEntryPOS2 = new MapMaker().concurrencyLevel(2).makeMap(); - for (CoreMap sentence : sentences) { - for (IMWE token : sentence.get(JMWEAnnotation.class)) { - if (token.isInflected()) { - inflectedCounterPositive1++; - } else { - inflectedCounterNegative++; - } - strTokenForm1.put(strTokenForm1.size() + 1, token.getForm()); - strTokenGetEntry1.put(strTokenGetEntry1.size() + 1, token.getEntry().toString().substring(token.getEntry().toString().length() - 1)); - Collection values = token.getPartMap().values(); - IMWEDesc entry = token.getEntry(); - MarkedContinuousCounter1 += entry.getMarkedContinuous(); - UnmarkedPatternCounter += entry.getUnmarkedPattern(); - for (IMWEDesc.IPart iPart : values) { - strTokenGetiPart1.put(strTokenGetiPart1.size() + 1, iPart.getForm()); - } - for (String strPostPrefix : entry.getPOS().getPrefixes()) { - strTokenEntryPOS1.put(strTokenEntryPOS1.size() + 1, strPostPrefix); - } - for (IToken tokens : token.getTokens()) { - ITokenMapTag1.put(ITokenMapTag1.size() + 1, tokens.getTag()); - for (String strtoken : tokens.getStems()) { - strTokenStems1.put(strTokenStems1.size() + 1, strtoken); - } - } - tokensCounter1++; - } - anotatorcounter1++; - } - jmweStrAnnotation = new Annotation(str1); - pipelineJMWE.annotate(jmweStrAnnotation); - sentences = jmweStrAnnotation.get(CoreAnnotations.SentencesAnnotation.class); - for (CoreMap sentence : sentences) { - for (IMWE token : sentence.get(JMWEAnnotation.class)) { - if (token.isInflected()) { - inflectedCounterPositive2++; - } else { - inflectedCounterNegative--; - } - strTokenForm2.put(strTokenForm2.size() + 1, token.getForm()); - strTokenGetEntry2.put(strTokenGetEntry2.size() + 1, token.getEntry().toString().substring(token.getEntry().toString().length() - 1)); - Collection values = token.getPartMap().values(); - IMWEDesc entry = token.getEntry(); - MarkedContinuousCounter2 += entry.getMarkedContinuous(); - UnmarkedPatternCounter += entry.getUnmarkedPattern(); - for (IMWEDesc.IPart iPart : values) { - strTokenGetiPart2.put(strTokenGetiPart2.size() + 1, iPart.getForm()); - } - for (String strPostPrefix : entry.getPOS().getPrefixes()) { - strTokenEntryPOS2.put(strTokenEntryPOS2.size() + 1, strPostPrefix); - } - for (IToken tokens : token.getTokens()) { - ITokenMapTag2.put(ITokenMapTag2.size() + 1, tokens.getTag()); - for (String strtoken : tokens.getStems()) { - strTokenStems2.put(strTokenStems2.size() + 1, strtoken); - } - } - tokensCounter2++; - } - anotatorcounter2++; - } - for (String strTokenPos1 : strTokenEntryPOS1.values()) { - for (String strTokenPos2 : strTokenEntryPOS2.values()) { - if (strTokenPos1.equals(strTokenPos2)) { - score += 500; - } - } - } - score += UnmarkedPatternCounter * 1600; - if (MarkedContinuousCounter1 > 0 && MarkedContinuousCounter2 > 0) { - score += MarkedContinuousCounter1 > MarkedContinuousCounter2 ? (MarkedContinuousCounter1 - MarkedContinuousCounter2) * 500 - : (MarkedContinuousCounter2 - MarkedContinuousCounter1) * 500; - } - for (String strTokeniPart1 : strTokenGetiPart1.values()) { - for (String strTokeniPart2 : strTokenGetiPart2.values()) { - if (strTokeniPart1.equals(strTokeniPart2)) { - score += 400; - } - } - } - for (String strTokenEntry1 : strTokenGetEntry1.values()) { - for (String strTokenEntry2 : strTokenGetEntry2.values()) { - if (strTokenEntry1.equals(strTokenEntry2)) { - score += 2500; - } - } - } - for (String strmapTag : ITokenMapTag1.values()) { - for (String strmapTag1 : ITokenMapTag2.values()) { - if (strmapTag.equals(strmapTag1)) { - score += 1450; - } - } - } - for (String strTokenForm1itr1 : strTokenForm1.values()) { - for (String strTokenForm1itr2 : strTokenForm2.values()) { - if (strTokenForm1itr1.equals(strTokenForm1itr2)) { - score += 2600; - } else if (strTokenForm1itr1.contains(strTokenForm1itr2)) { - score += 500; - } - } - } - for (String strTokenStem : strTokenStems1.values()) { - for (String strTokenStem1 : strTokenStems2.values()) { - if (strTokenStem.equals(strTokenStem1)) { - score += 1500; - } - } - } - if (inflectedCounterPositive1 + inflectedCounterPositive2 > inflectedCounterNegative && inflectedCounterNegative > 0) { - score += (inflectedCounterPositive1 - inflectedCounterNegative) * 650; - } - if (inflectedCounterPositive1 > 0 && inflectedCounterPositive2 > 0) { - score += ((inflectedCounterPositive1 + inflectedCounterPositive2) - inflectedCounterNegative) * 550; - } - if (anotatorcounter1 > 1 && anotatorcounter2 > 1) { - score += (anotatorcounter1 + anotatorcounter2) * 400; - } - if (tokensCounter1 > 0 && tokensCounter2 > 0) { - score += (tokensCounter1 + tokensCounter2) * 400; - } else { - score -= tokensCounter1 >= tokensCounter2 ? (tokensCounter1 - tokensCounter2) * 500 : (tokensCounter2 - tokensCounter1) * 500; - } - LevenshteinDistance leven = new LevenshteinDistance(str, str1); - int SentenceScoreDiff = leven.computeLevenshteinDistance(); - SentenceScoreDiff *= 15; - score -= SentenceScoreDiff; - System.out.println("Final current score: " + score + "\nSentence 1: " + str + "\nSentence 2: " + str1 + "\n"); - smxParam.setDistance(score); - } catch (Exception ex) { - System.out.println("ex: " + ex.getMessage() + "\n"); - smxParam.setDistance(-1000); - return smxParam; } + sentenceConstituencyParseList.clear(); + ConcurrentMap simpleSMXlist = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap simpleSMXlistVector = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap sentiment1 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap sentiment2 = new MapMaker().concurrencyLevel(2).makeMap(); + for (CoreMap sentence : pipelineAnnotation1Sentiment.get(CoreAnnotations.SentencesAnnotation.class)) { + Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class); + sentiment1.put(sentiment1.size(), RNNCoreAnnotations.getPredictedClass(tree)); + SimpleMatrix predictions = RNNCoreAnnotations.getPredictions(tree); + SimpleMatrix nodeVector = RNNCoreAnnotations.getNodeVector(tree); + simpleSMXlist.put(simpleSMXlist.size(), predictions); + simpleSMXlistVector.put(simpleSMXlistVector.size() + 1, nodeVector); + } + for (CoreMap sentence : pipelineAnnotation2Sentiment.get(CoreAnnotations.SentencesAnnotation.class)) { + Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class); + sentiment2.put(sentiment2.size() + 1, RNNCoreAnnotations.getPredictedClass(tree)); + SimpleMatrix predictions = RNNCoreAnnotations.getPredictions(tree); + SimpleMatrix nodeVector = RNNCoreAnnotations.getNodeVector(tree); + score = simpleSMXlist.values().stream().map((simpleSMX) -> predictions.dot(simpleSMX) * 100).map((dot) -> dot > 50 ? dot - 50 : 50 - dot).map((subtracter) -> { + subtracter *= 25; + return subtracter; + }).map((subtracter) -> subtracter).reduce(score, (accumulator, _item) -> accumulator - _item); + for (SimpleMatrix simpleSMX : simpleSMXlistVector.values()) { + double dot = nodeVector.dot(simpleSMX); + double elementSum = nodeVector.kron(simpleSMX).elementSum(); + elementSum = Math.round(elementSum * 100.0) / 100.0; + if (dot < 0.1) { + score += 256; + } + if (elementSum < 0.1 && elementSum > 0.0) { + score += 1300; + } else if (elementSum > 0.1 && elementSum < 1.0) { + score -= 1100; + } else { + score -= 1424; + } + } + } + score -= (sentiment1.size() > sentiment2.size() ? sentiment1.size() - sentiment2.size() : sentiment2.size() - sentiment1.size()) * 500; + DocumentReaderAndWriter readerAndWriter = classifier.makePlainTextReaderAndWriter(); + List classifyRaw1 = classifier.classifyRaw(str, readerAndWriter); + List classifyRaw2 = classifier.classifyRaw(str1, readerAndWriter); + score -= (classifyRaw1.size() > classifyRaw2.size() ? classifyRaw1.size() - classifyRaw2.size() : classifyRaw2.size() - classifyRaw1.size()) * 200; + int mainSentiment1 = 0; + int longest1 = 0; + int mainSentiment2 = 0; + int longest2 = 0; + for (CoreMap sentence : pipelineAnnotation1Sentiment.get(CoreAnnotations.SentencesAnnotation.class)) { + Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class); + int sentiment = RNNCoreAnnotations.getPredictedClass(tree); + String partText = sentence.toString(); + SimpleMatrix predictions = RNNCoreAnnotations.getPredictions(tree); + if (partText.length() > longest1) { + mainSentiment1 = sentiment; + longest1 = partText.length(); + } + } + for (CoreMap sentence : pipelineAnnotation2Sentiment.get(CoreAnnotations.SentencesAnnotation.class)) { + Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class); + int sentiment = RNNCoreAnnotations.getPredictedClass(tree); + SimpleMatrix predictions = RNNCoreAnnotations.getPredictions(tree); + String partText = sentence.toString(); + if (partText.length() > longest2) { + mainSentiment2 = sentiment; + longest2 = partText.length(); + } + } + if (longest1 != longest2) { + long deffLongest = longest1 > longest2 ? longest1 : longest2; + long deffshorter = longest1 < longest2 ? longest1 : longest2; + if (deffLongest >= (deffshorter * 2) - 1 && deffLongest - deffshorter <= 45) { + score += (deffLongest - deffshorter) * 200; + } else if (mainSentiment1 != mainSentiment2 && deffLongest - deffshorter > 20 && deffLongest - deffshorter < 45) { + score += (deffLongest - deffshorter) * 200; + } else { + score -= (deffLongest - deffshorter) * 50; + } + } + List sentences = jmweStrAnnotation1.get(CoreAnnotations.SentencesAnnotation.class); + int tokensCounter1 = 0; + int tokensCounter2 = 0; + int anotatorcounter1 = 0; + int anotatorcounter2 = 0; + int inflectedCounterPositive1 = 0; + int inflectedCounterPositive2 = 0; + int inflectedCounterNegative = 0; + int MarkedContinuousCounter1 = 0; + int MarkedContinuousCounter2 = 0; + int UnmarkedPatternCounter = 0; + ConcurrentMap ITokenMapTag1 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap ITokenMapTag2 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap strTokenStems1 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap strTokenStems2 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap strTokenForm1 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap strTokenForm2 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap strTokenGetEntry1 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap strTokenGetEntry2 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap strTokenGetiPart1 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap strTokenGetiPart2 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap strTokenEntryPOS1 = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap strTokenEntryPOS2 = new MapMaker().concurrencyLevel(2).makeMap(); + for (CoreMap sentence : sentences) { + for (IMWE token : sentence.get(JMWEAnnotation.class)) { + if (token.isInflected()) { + inflectedCounterPositive1++; + } else { + inflectedCounterNegative++; + } + strTokenForm1.put(strTokenForm1.size() + 1, token.getForm()); + strTokenGetEntry1.put(strTokenGetEntry1.size() + 1, token.getEntry().toString().substring(token.getEntry().toString().length() - 1)); + Collection values = token.getPartMap().values(); + IMWEDesc entry = token.getEntry(); + MarkedContinuousCounter1 += entry.getMarkedContinuous(); + UnmarkedPatternCounter += entry.getUnmarkedPattern(); + for (IMWEDesc.IPart iPart : values) { + strTokenGetiPart1.put(strTokenGetiPart1.size() + 1, iPart.getForm()); + } + for (String strPostPrefix : entry.getPOS().getPrefixes()) { + strTokenEntryPOS1.put(strTokenEntryPOS1.size() + 1, strPostPrefix); + } + for (IToken tokens : token.getTokens()) { + ITokenMapTag1.put(ITokenMapTag1.size() + 1, tokens.getTag()); + for (String strtoken : tokens.getStems()) { + strTokenStems1.put(strTokenStems1.size() + 1, strtoken); + } + } + tokensCounter1++; + } + anotatorcounter1++; + } + sentences = jmweStrAnnotation2.get(CoreAnnotations.SentencesAnnotation.class); + for (CoreMap sentence : sentences) { + for (IMWE token : sentence.get(JMWEAnnotation.class)) { + if (token.isInflected()) { + inflectedCounterPositive2++; + } else { + inflectedCounterNegative--; + } + strTokenForm2.put(strTokenForm2.size() + 1, token.getForm()); + strTokenGetEntry2.put(strTokenGetEntry2.size() + 1, token.getEntry().toString().substring(token.getEntry().toString().length() - 1)); + Collection values = token.getPartMap().values(); + IMWEDesc entry = token.getEntry(); + MarkedContinuousCounter2 += entry.getMarkedContinuous(); + UnmarkedPatternCounter += entry.getUnmarkedPattern(); + for (IMWEDesc.IPart iPart : values) { + strTokenGetiPart2.put(strTokenGetiPart2.size() + 1, iPart.getForm()); + } + for (String strPostPrefix : entry.getPOS().getPrefixes()) { + strTokenEntryPOS2.put(strTokenEntryPOS2.size() + 1, strPostPrefix); + } + for (IToken tokens : token.getTokens()) { + ITokenMapTag2.put(ITokenMapTag2.size() + 1, tokens.getTag()); + for (String strtoken : tokens.getStems()) { + strTokenStems2.put(strTokenStems2.size() + 1, strtoken); + } + } + tokensCounter2++; + } + anotatorcounter2++; + } + for (String strTokenPos1 : strTokenEntryPOS1.values()) { + for (String strTokenPos2 : strTokenEntryPOS2.values()) { + if (strTokenPos1.equals(strTokenPos2)) { + score += 500; + } + } + } + score += UnmarkedPatternCounter * 1600; + if (MarkedContinuousCounter1 > 0 && MarkedContinuousCounter2 > 0) { + score += MarkedContinuousCounter1 > MarkedContinuousCounter2 ? (MarkedContinuousCounter1 - MarkedContinuousCounter2) * 500 + : (MarkedContinuousCounter2 - MarkedContinuousCounter1) * 500; + } + for (String strTokeniPart1 : strTokenGetiPart1.values()) { + for (String strTokeniPart2 : strTokenGetiPart2.values()) { + if (strTokeniPart1.equals(strTokeniPart2)) { + score += 400; + } + } + } + for (String strTokenEntry1 : strTokenGetEntry1.values()) { + for (String strTokenEntry2 : strTokenGetEntry2.values()) { + if (strTokenEntry1.equals(strTokenEntry2)) { + score += 2500; + } + } + } + for (String strmapTag : ITokenMapTag1.values()) { + for (String strmapTag1 : ITokenMapTag2.values()) { + if (strmapTag.equals(strmapTag1)) { + score += 1450; + } + } + } + for (String strTokenForm1itr1 : strTokenForm1.values()) { + for (String strTokenForm1itr2 : strTokenForm2.values()) { + if (strTokenForm1itr1.equals(strTokenForm1itr2)) { + score += 2600; + } else if (strTokenForm1itr1.contains(strTokenForm1itr2)) { + score += 500; + } + } + } + for (String strTokenStem : strTokenStems1.values()) { + for (String strTokenStem1 : strTokenStems2.values()) { + if (strTokenStem.equals(strTokenStem1)) { + score += 1500; + } + } + } + if (inflectedCounterPositive1 + inflectedCounterPositive2 > inflectedCounterNegative && inflectedCounterNegative > 0) { + score += (inflectedCounterPositive1 - inflectedCounterNegative) * 650; + } + if (inflectedCounterPositive1 > 0 && inflectedCounterPositive2 > 0) { + score += ((inflectedCounterPositive1 + inflectedCounterPositive2) - inflectedCounterNegative) * 550; + } + if (anotatorcounter1 > 1 && anotatorcounter2 > 1) { + score += (anotatorcounter1 + anotatorcounter2) * 400; + } + if (tokensCounter1 > 0 && tokensCounter2 > 0) { + score += (tokensCounter1 + tokensCounter2) * 400; + } else { + score -= tokensCounter1 >= tokensCounter2 ? (tokensCounter1 - tokensCounter2) * 500 : (tokensCounter2 - tokensCounter1) * 500; + } + LevenshteinDistance leven = new LevenshteinDistance(str, str1); + int SentenceScoreDiff = leven.computeLevenshteinDistance(); + SentenceScoreDiff *= 15; + score -= SentenceScoreDiff; + System.out.println("Final current score: " + score + "\nSentence 1: " + str + "\nSentence 2: " + str1 + "\n"); + smxParam.setDistance(score); return smxParam; } - } diff --git a/ArtificialAutism/src/main/java/PresentationLayer/DiscordHandler.java b/ArtificialAutism/src/main/java/PresentationLayer/DiscordHandler.java index 3c04eabe..6efa12d0 100644 --- a/ArtificialAutism/src/main/java/PresentationLayer/DiscordHandler.java +++ b/ArtificialAutism/src/main/java/PresentationLayer/DiscordHandler.java @@ -12,8 +12,6 @@ nohup screen -d -m -S nonroot java -Xmx6800M -jar /home/javatests/ArtificialAut screen -ls (number1) screen -X -S (number1) quit */ -//https://discordapp.com/developers/applications/ -//https://github.com/Javacord/Javacord package PresentationLayer; import FunctionLayer.CustomError; @@ -43,11 +41,13 @@ public class DiscordHandler { Logger.getLogger(DiscordHandler.class.getName()).log(Level.SEVERE, null, ex); } }).start(); - MYSQLDatahandler.shiftReduceParserInitiate(); + MYSQLDatahandler.instance.shiftReduceParserInitiate(); MYSQLDatahandler.instance.instantiateExecutor(); + MYSQLDatahandler.instance.updateStringCache(); + MYSQLDatahandler.instance.instantiateAnnotationMap(); if (MYSQLDatahandler.instance.getstringCacheSize() != 0) { - while (MYSQLDatahandler.instance.getlHMSMXSize() * MYSQLDatahandler.instance.getlHMSMXSize() * 2 - < (MYSQLDatahandler.instance.getstringCacheSize() + while (MYSQLDatahandler.instance.getlHMSMXSize() * MYSQLDatahandler.instance.getlHMSMXSize() * 5 + < (MYSQLDatahandler.instance.getstringCacheSize() * MYSQLDatahandler.instance.getstringCacheSize()) - MYSQLDatahandler.instance.getstringCacheSize()) { MYSQLDatahandler.instance.checkIfUpdateMatrixes(); @@ -62,12 +62,6 @@ public class DiscordHandler { strtest = strtest.substring(9, strtest.length() - 1); boolean channelpermissionsDenied = false; switch (strtest) { - case "Server Area": { - if (!event.getServerTextChannel().get().toString().contains("chat-live")) { - channelpermissionsDenied = true; - } - break; - } case "Public Area": { break; } diff --git a/ArtificialAutism/target/ArtificialAutism-1.0.jar b/ArtificialAutism/target/ArtificialAutism-1.0.jar index b546e6a7e76418d600e633c7594f84f33c599414..a3d3e067e74158e82fb7f9d47f599fc45e108071 100644 GIT binary patch delta 30435 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

SL*h8~MeQ4 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 delta 27758 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