Advertisement
Guest User

Untitled

a guest
Apr 8th, 2020
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 12.57 KB | None | 0 0
  1. package ru.liboskat.task6;
  2.  
  3. import com.fasterxml.jackson.annotation.JsonProperty;
  4. import com.fasterxml.jackson.dataformat.xml.XmlMapper;
  5. import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
  6. import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
  7. import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
  8. import org.apache.commons.math3.linear.*;
  9. import ru.stachek66.nlp.mystem.holding.Factory;
  10. import ru.stachek66.nlp.mystem.holding.MyStem;
  11. import ru.stachek66.nlp.mystem.holding.MyStemApplicationException;
  12. import ru.stachek66.nlp.mystem.holding.Request;
  13. import ru.stachek66.nlp.mystem.model.Info;
  14. import scala.Option;
  15. import scala.collection.JavaConversions;
  16.  
  17. import java.io.BufferedReader;
  18. import java.io.File;
  19. import java.io.IOException;
  20. import java.io.InputStreamReader;
  21. import java.nio.file.Files;
  22. import java.nio.file.Paths;
  23. import java.util.*;
  24. import java.util.function.Function;
  25. import java.util.stream.Collectors;
  26.  
  27. public class VectorSearchUtil {
  28.     public static final int K = 20;
  29.  
  30.     private static final XmlMapper mapper = new XmlMapper();
  31.     private final static MyStem mystemAnalyzer = new Factory("-igd --eng-gr --format json --weight")
  32.             .newMyStem("3.0", Option.empty()).get();
  33.  
  34.     public static void main(String[] args) throws IOException {
  35.         List<Term> terms = mapper.readValue(new File("src/ru/liboskat/task6/inverted_index.xml"), Terms.class)
  36.                 .getTerm();
  37.         List<Article> documents = mapper.readValue(new File("example.xml"), Documents.class).getDocument();
  38.         int termCount = terms.size();
  39.         int documentsCount = documents.size();
  40.  
  41.         double[][] matrix = new double[termCount][documentsCount];
  42.         for (int i = 0; i < termCount; i++) {
  43.             int termId = i;
  44.             terms.get(termId).getDoc().forEach(doc -> matrix[termId][doc.getId() - 1] = doc.getTfIdf());
  45.         }
  46.  
  47.         RealMatrix realMatrix = MatrixUtils.createRealMatrix(matrix);
  48.         SingularValueDecomposition decomposition = new SingularValueDecomposition(realMatrix);
  49.         RealMatrix uk = decomposition.getU().getSubMatrix(0, matrix.length - 1, 0, K - 1);
  50.         RealMatrix sk = decomposition.getS().getSubMatrix(0, K - 1, 0, K - 1);
  51.         RealMatrix skInverse = MatrixUtils.inverse(sk);
  52.  
  53.         List<SearchResult> searchResults = readQueries().stream()
  54.                 .map(query -> getSearchResult(query, terms, documents, realMatrix, uk, skInverse))
  55.                 .collect(Collectors.toList());
  56.         Files.write(Paths.get("src/ru/liboskat/task6/vector_search_result.txt"),
  57.                 searchResults.stream().map(SearchResult::toString).collect(Collectors.toList()));
  58.     }
  59.  
  60.     private static SearchResult getSearchResult(String query, List<Term> terms, List<Article> documents,
  61.                                                 RealMatrix realMatrix, RealMatrix uk, RealMatrix skInverse) {
  62.         RealMatrix q = getSimpleQueryVector(query, terms).multiply(uk).multiply(skInverse);
  63.  
  64.         List<ArticleSearchResult> articleSearchResults = new ArrayList<>();
  65.         for (int j = 0; j < documents.size(); j++) {
  66.             RealMatrix d = realMatrix.getColumnMatrix(j).transpose().multiply(uk).multiply(skInverse);
  67.  
  68.             Article doc = documents.get(j);
  69.             articleSearchResults.add(
  70.                     new ArticleSearchResult(doc.getId(), doc.getTitle(), doc.getUrl(), getSimilarity(q, d)));
  71.         }
  72.         return new SearchResult(query, articleSearchResults.stream()
  73.                 .sorted(Comparator.comparing(ArticleSearchResult::getScore).reversed())
  74.                 .limit(10)
  75.                 .collect(Collectors.toList()));
  76.     }
  77.  
  78.     private static double getSimilarity(RealMatrix q, RealMatrix d) {
  79.         double vectorsProduct = 0.0;
  80.         double documentVectorSumOfSquares = 0.0;
  81.         double queryVectorSumOfSquares = 0;
  82.         for (int i = 0; i < K; i++) {
  83.             double documentVectorElement = d.getEntry(0, i);
  84.             double queryVectorElement = q.getEntry(0, i);
  85.             vectorsProduct += documentVectorElement * queryVectorElement;
  86.             documentVectorSumOfSquares += documentVectorElement * documentVectorElement;
  87.             queryVectorSumOfSquares += queryVectorElement * queryVectorElement;
  88.         }
  89.         if (documentVectorSumOfSquares == 0 || queryVectorSumOfSquares == 0) {
  90.             return 0;
  91.         } else {
  92.             return vectorsProduct / (Math.sqrt(documentVectorSumOfSquares) * Math.sqrt(queryVectorSumOfSquares));
  93.         }
  94.     }
  95.  
  96.     private static RealMatrix getSimpleQueryVector(String query, List<Term> terms) {
  97.         List<String> queryParts = Arrays.stream(query.split(" "))
  98.                 .peek(VectorSearchUtil::stem)
  99.                 .collect(Collectors.toList());
  100.  
  101.         double[] queryVector = new double[terms.size()];
  102.         for (int i = 0; i < terms.size(); i++) {
  103.             queryVector[i] = queryParts.contains(terms.get(i).getValue()) ? 1 : 0;
  104.         }
  105.         return MatrixUtils.createRowRealMatrix(queryVector);
  106.     }
  107.  
  108.     private static String stem(String word) {
  109.         try {
  110.             List<Info> result =
  111.                     JavaConversions.seqAsJavaList(
  112.                             mystemAnalyzer
  113.                                     .analyze(Request.apply(word))
  114.                                     .info()
  115.                                     .toSeq());
  116.             if (!result.isEmpty() && result.get(0).lex().nonEmpty()) {
  117.                 return result.get(0).lex().get();
  118.             }
  119.             return word;
  120.         } catch (MyStemApplicationException e) {
  121.             throw new IllegalArgumentException(e);
  122.         }
  123.     }
  124.  
  125.     private static List<String> readQueries() throws IOException {
  126.         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  127.         System.out.println("Введите число запросов");
  128.         int numberOfQueries = Integer.parseInt(br.readLine());
  129.         List<String> queries = new ArrayList<>();
  130.         System.out.println("Введите " + numberOfQueries + " запросов");
  131.         for (int i = 0; i < numberOfQueries; i++) {
  132.             queries.add(br.readLine());
  133.         }
  134.         br.close();
  135.         return queries;
  136.     }
  137.  
  138.     private static class SearchResult {
  139.         private String query;
  140.         private List<ArticleSearchResult> found;
  141.  
  142.         public SearchResult(String query, List<ArticleSearchResult> found) {
  143.             this.query = query;
  144.             this.found = found;
  145.         }
  146.  
  147.         @Override
  148.         public String toString() {
  149.             StringBuilder stringBuilder = new StringBuilder();
  150.             stringBuilder.append("Запрос='");
  151.             stringBuilder.append(query);
  152.             stringBuilder.append("',\nНайдено=");
  153.             if (found.size() == 0) {
  154.                 stringBuilder.append("ничего");
  155.             } else {
  156.                 stringBuilder.append("{\n");
  157.                 found.forEach(articleSearchResult -> {
  158.                     stringBuilder.append("  ");
  159.                     stringBuilder.append(articleSearchResult);
  160.                     stringBuilder.append(",\n");
  161.                 });
  162.                 stringBuilder.append("},");
  163.             }
  164.             stringBuilder.append("\n");
  165.             return stringBuilder.toString();
  166.         }
  167.     }
  168.  
  169.     private static class ArticleSearchResult {
  170.         private Integer id;
  171.         private String title;
  172.         private String url;
  173.         private Double score;
  174.  
  175.         public ArticleSearchResult(Integer id, String title, String url, Double score) {
  176.             this.id = id;
  177.             this.title = title;
  178.             this.url = url;
  179.             this.score = score;
  180.         }
  181.  
  182.         public Integer getId() {
  183.             return id;
  184.         }
  185.  
  186.         public Double getScore() {
  187.             return score;
  188.         }
  189.  
  190.         @Override
  191.         public String toString() {
  192.             return "Статья{" +
  193.                     "url='" + url + '\'' +
  194.                     ", score='" + score + '\'' +
  195.                     '}';
  196.         }
  197.     }
  198.  
  199.     @JacksonXmlRootElement(localName = "terms")
  200.     private static class Terms {
  201.         @JacksonXmlElementWrapper(useWrapping = false)
  202.         private List<Term> term;
  203.  
  204.         public Terms() {
  205.         }
  206.  
  207.         public Terms(List<Term> term) {
  208.             this.term = term;
  209.         }
  210.  
  211.         public List<Term> getTerm() {
  212.             return term;
  213.         }
  214.  
  215.         public void setTerm(List<Term> term) {
  216.             this.term = term;
  217.         }
  218.     }
  219.  
  220.     private static class Term {
  221.         @JacksonXmlProperty(isAttribute = true)
  222.         private String value;
  223.  
  224.         @JacksonXmlElementWrapper(useWrapping = false)
  225.         private List<Document> doc;
  226.  
  227.         public Term() {
  228.         }
  229.  
  230.         public Term(String value, List<Document> doc) {
  231.             this.value = value;
  232.             this.doc = doc;
  233.         }
  234.  
  235.         public Optional<Document> findDocument(int documentId) {
  236.             return doc.stream().filter(document -> document.getId().equals(documentId)).findAny();
  237.         }
  238.  
  239.         public String getValue() {
  240.             return value;
  241.         }
  242.  
  243.         public void setValue(String value) {
  244.             this.value = value;
  245.         }
  246.  
  247.         public List<Document> getDoc() {
  248.             return doc;
  249.         }
  250.  
  251.         public void setDoc(List<Document> doc) {
  252.             this.doc = doc;
  253.         }
  254.     }
  255.  
  256.     private static class Document implements Comparable<Document> {
  257.         @JacksonXmlProperty(isAttribute = true)
  258.         private Integer id;
  259.  
  260.         @JacksonXmlProperty(isAttribute = true)
  261.         private Long count;
  262.  
  263.         @JacksonXmlProperty(isAttribute = true)
  264.         private Double tfIdf;
  265.  
  266.         public Document() {
  267.         }
  268.  
  269.         public Document(Integer id, Long count) {
  270.             this.id = id;
  271.             this.count = count;
  272.         }
  273.  
  274.         public Integer getId() {
  275.             return id;
  276.         }
  277.  
  278.         public void setId(Integer id) {
  279.             this.id = id;
  280.         }
  281.  
  282.         public Long getCount() {
  283.             return count;
  284.         }
  285.  
  286.         public void setCount(Long count) {
  287.             this.count = count;
  288.         }
  289.  
  290.         @JsonProperty("tf-idf")
  291.         public Double getTfIdf() {
  292.             return tfIdf;
  293.         }
  294.  
  295.         public void setTfIdf(Double tfIdf) {
  296.             this.tfIdf = tfIdf;
  297.         }
  298.  
  299.         @Override
  300.         public int compareTo(Document o) {
  301.             return Comparator
  302.                     .comparing(Document::getCount)
  303.                     .reversed()
  304.                     .thenComparing(Document::getId)
  305.                     .compare(this, o);
  306.         }
  307.     }
  308.  
  309.     @JacksonXmlRootElement(localName = "documents")
  310.     private static class Documents {
  311.         @JacksonXmlElementWrapper(useWrapping = false)
  312.         private List<Article> document;
  313.  
  314.         public Documents() {
  315.         }
  316.  
  317.         public Documents(List<Article> document) {
  318.             this.document = document;
  319.         }
  320.  
  321.         public Article findArticle(int id) {
  322.             return getDocument().stream()
  323.                     .filter(article -> id == article.getId())
  324.                     .findAny().orElseThrow(IllegalArgumentException::new);
  325.         }
  326.  
  327.         public List<Article> getDocument() {
  328.             return document;
  329.         }
  330.  
  331.         public void setDocument(List<Article> document) {
  332.             this.document = document;
  333.         }
  334.     }
  335.  
  336.     private static class Article {
  337.         @JacksonXmlProperty(isAttribute = true)
  338.         private Integer id;
  339.         private String url;
  340.         private String title;
  341.         private String text;
  342.         private String keywords;
  343.  
  344.         public Article() {
  345.         }
  346.  
  347.         public Integer getId() {
  348.             return id;
  349.         }
  350.  
  351.         public void setId(Integer id) {
  352.             this.id = id;
  353.         }
  354.  
  355.         public String getUrl() {
  356.             return url;
  357.         }
  358.  
  359.         public void setUrl(String url) {
  360.             this.url = url;
  361.         }
  362.  
  363.         public String getTitle() {
  364.             return title;
  365.         }
  366.  
  367.         public void setTitle(String title) {
  368.             this.title = title;
  369.         }
  370.  
  371.         public String getText() {
  372.             return text;
  373.         }
  374.  
  375.         public void setText(String text) {
  376.             this.text = text;
  377.         }
  378.  
  379.         public String getKeywords() {
  380.             return keywords;
  381.         }
  382.  
  383.         public void setKeywords(String keywords) {
  384.             this.keywords = keywords;
  385.         }
  386.     }
  387. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement