package com.formulasearchengine.mlp.evaluation;
import com.formulasearchengine.mlp.evaluation.pojo.GoldEntry;
import com.formulasearchengine.mlp.evaluation.pojo.IdentifierDefinition;
import com.formulasearchengine.mlp.evaluation.pojo.ScoreSummary;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.junit.Assert;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.*;
import static org.junit.Assert.*;
/**
* Created by Leo on 21.10.2016.
*/
public class ExtractionTests {
public static final String FOLDER = "formulasearchengine/mlp/gold/";
public static final String GOLDFILE_SAMPLE = FOLDER + "gold_sample.json";
public static final String GOLDFILE_SAMPLE_2 = FOLDER + "gold_sample2.json";
public static final String GOLDFILE_UNSORTED = FOLDER + "gold_unsorted_sample.json";
public static final String EXTRACTIONS = FOLDER + "extraction.csv";
public static final String EXTRACTIONS_SAMPLE = FOLDER + "extraction_sample.csv";
public static final String EXTRACTIONS_SAMPLE_LINK_WIKIDATA_NORMAL = FOLDER + "extraction_sample_link_wikidata_normal.csv";
public static final String EXTRACTIONS_SAMPLE_EXTRACTIONS_NO_QID = FOLDER + "extraction_sample_noQid.csv";
public static final String EXTRACTIONS_UNSORTED = FOLDER + "extraction_unsorted.csv";
public static final String EXTRACTIONS_SAMPLE_WRONG = FOLDER + "extraction_sample_wrong.csv";
public static final String EXTRACTIONS_SAMPLE_WRONG_2 = FOLDER + "extraction_sample_wrong2.csv";
public static final String EXTRACTIONS_SAMPLE_WIKIDATA = FOLDER + "extraction_sample_wikidata.csv";
public static final String EXTRACTIONS_SAMPLE_WIKIDATA_2 = FOLDER + "extraction_sample_wikidata2.csv";
public static final int NUMBER_OF_FORMULAS = 100;
public static final int TOTAL_NUMBER_OF_DEFINITIONS = 575;
public static final int TOTAL_NUMBER_OF_TEXT_DEFINITIONS = 359;
public static final int TOTAL_NUMBER_OF_WIKIDATA_LINKS = 216;
public static final int TOTAL_NUMBER_OF_IDENTIFIERS = 310;
public static final int TOTAL_NUMBER_OF_EXTRACTED_DEFINITIONS = 425;
public static final int TOTAL_NUMBER_OF_IDENTIFIERS_WITH_DEFINITIONS = 87;
public static final int TRUE_POSITIVES = 69;
public static final int FALSE_POSITIVES = 351;
public static final int UNSORTED_TP = 3;
public static final int UNSORTED_TOTAL_IDENTIFIERS = 7;
public static final int UNSORTED_TOTAL_EXTRACTIONS = 15;
public static final int DUPLICATE_TP = 5;
public File getFile(String file) {
ClassLoader classLoader = getClass().getClassLoader();
return new File(classLoader.getResource(file).getFile());
}
@Test
public void testGoldReading() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold_withWikidata = evaluator.readGoldEntries(getFile(GOLDFILE_SAMPLE));
List<GoldEntry> gold_withoutWikidata = evaluator.readGoldEntries(getFile(GOLDFILE_SAMPLE_2));
assertEquals(gold_withoutWikidata.size(), 1);
ArrayList<IdentifierDefinition> definitions = new ArrayList<>();
definitions.add(new IdentifierDefinition("q", "probability"));
//without wikidata
assertEquals(1, gold_withoutWikidata.size());
assertEquals(new GoldEntry("41", "3545", "1", "q^{42}", "Martingale_(betting_system)", definitions), gold_withoutWikidata.get(0));
//with wikidata
definitions.add(0, new IdentifierDefinition("q", "Q9492"));
assertEquals(1, gold_withWikidata.size());
assertEquals(new GoldEntry("41", "3545", "1", "q^{42}", "Martingale_(betting_system)", definitions), gold_withWikidata.get(0));
}
@Test
public void testFullGoldReading() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(Evaluator.GOLDFILE));
//number of formula
assertEquals(NUMBER_OF_FORMULAS, gold.size());
//total number of definitions (575), 359 text definitions, 216 wikidata links
assertEquals(TOTAL_NUMBER_OF_DEFINITIONS, gold.stream().flatMap(g -> g.getDefinitions().stream()).count());
assertEquals(TOTAL_NUMBER_OF_TEXT_DEFINITIONS, gold.stream().flatMap(g -> g.getDefinitions().stream().filter(d -> d.getDefinition().matches("(^(?!q\\d+).*)$"))).count());
assertEquals(TOTAL_NUMBER_OF_WIKIDATA_LINKS, gold.stream().flatMap(g -> g.getDefinitions().stream().filter(d -> d.getDefinition().matches("(^(q\\d+).*)$"))).count());
//number of distinct identifiers
assertEquals(TOTAL_NUMBER_OF_IDENTIFIERS, gold.stream().flatMap(g -> g.getDefinitions().stream().map(i -> i.getIdentifier()).distinct()).count());
ArrayList<IdentifierDefinition> definitions = new ArrayList<>();
definitions.add(new IdentifierDefinition("q", "q9492"));
definitions.add(new IdentifierDefinition("q", "probability"));
//0 indexed but the first qId is 1 => 40 == 41
assertEquals(new GoldEntry("41", "3545", "1", "q^{42}", "Martingale_(betting_system)", definitions), gold.get(40));
}
@Test
public void testExtractionReading() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(GOLDFILE_SAMPLE));
Multimap<String, IdentifierDefinition> extractions = evaluator.readExtractions(getFile(EXTRACTIONS_SAMPLE), gold);
Multimap<String, IdentifierDefinition> testData = ArrayListMultimap.create();
testData.put("41", new IdentifierDefinition("q", "tosses"));
assertEquals(extractions, testData);
}
@Test
public void testExtractionReadingFull() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(Evaluator.GOLDFILE));
Multimap<String, IdentifierDefinition> extractions = evaluator.readExtractions(getFile(EXTRACTIONS), gold);
assertEquals(TOTAL_NUMBER_OF_EXTRACTED_DEFINITIONS, extractions.entries().size());
assertEquals(TOTAL_NUMBER_OF_IDENTIFIERS_WITH_DEFINITIONS, extractions.keySet().size());
}
@Test(expected = IllegalArgumentException.class)
public void testExtractionReadingBadQId() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(GOLDFILE_SAMPLE));
evaluator.readExtractions(getFile(EXTRACTIONS_SAMPLE_WRONG), gold);
}
@Test(expected = IllegalArgumentException.class)
public void testExtractionReadingBadTitle() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(GOLDFILE_SAMPLE));
evaluator.readExtractions(getFile(EXTRACTIONS_SAMPLE_WRONG_2), gold);
}
@Test
public void testEvaluation() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(Evaluator.GOLDFILE));
Multimap<String, IdentifierDefinition> extractions = evaluator.readExtractions(getFile(EXTRACTIONS), gold);
ScoreSummary result = evaluator.evaluate(extractions, gold);
Assert.assertEquals(new ScoreSummary(TRUE_POSITIVES, DUPLICATE_TP, TOTAL_NUMBER_OF_IDENTIFIERS - TRUE_POSITIVES, FALSE_POSITIVES, 0), result);
}
@Test
public void testEvaluationTitleKey() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(Evaluator.GOLDFILE));
Multimap<String, IdentifierDefinition> extractions = evaluator.readExtractions(getFile(EXTRACTIONS), gold, true);
ScoreSummary result = evaluator.evaluate(extractions, gold, true);
Assert.assertEquals(new ScoreSummary(TRUE_POSITIVES, DUPLICATE_TP, TOTAL_NUMBER_OF_IDENTIFIERS - TRUE_POSITIVES, FALSE_POSITIVES, 0), result);
}
@Test
public void testEvaluation_no_qId() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(Evaluator.GOLDFILE));
Multimap<String, IdentifierDefinition> extractions = evaluator.readExtractions(getFile(EXTRACTIONS_SAMPLE_EXTRACTIONS_NO_QID), gold, true);
ScoreSummary result = evaluator.evaluate(extractions, gold, true);
Assert.assertEquals(new ScoreSummary(1, 0, TOTAL_NUMBER_OF_IDENTIFIERS - 1, 0, 0), result);
}
@Test
public void testEvaluation_entrie_with_link_wikidata_and_normal_definition() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(Evaluator.GOLDFILE));
Multimap<String, IdentifierDefinition> extractions = evaluator.readExtractions(getFile(EXTRACTIONS_SAMPLE_LINK_WIKIDATA_NORMAL), gold, true);
ScoreSummary result = evaluator.evaluate(extractions, gold, true);
Assert.assertEquals(new ScoreSummary(1, 2, TOTAL_NUMBER_OF_IDENTIFIERS - 1, 0, 1), result);
}
@Test
public void testEvaluationWithWikidataEntries() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(Evaluator.GOLDFILE));
Multimap<String, IdentifierDefinition> extractionsWikidata = evaluator.readExtractions(getFile(EXTRACTIONS_SAMPLE_WIKIDATA), gold);
Multimap<String, IdentifierDefinition> extractionsWikidata2 = evaluator.readExtractions(getFile(EXTRACTIONS_SAMPLE_WIKIDATA_2), gold);
ScoreSummary resultWikidata = evaluator.evaluate(extractionsWikidata, gold);
Assert.assertEquals(new ScoreSummary(1, 0, TOTAL_NUMBER_OF_IDENTIFIERS - 1, 0, 1), resultWikidata);
ScoreSummary resultWikidata2 = evaluator.evaluate(extractionsWikidata2, gold);
Assert.assertEquals(new ScoreSummary(1, 1, TOTAL_NUMBER_OF_IDENTIFIERS - 1, 0, 1), resultWikidata2);
}
@Test
public void testUnsortedEntries() throws IOException {
Evaluator evaluator = new Evaluator();
List<GoldEntry> gold = evaluator.readGoldEntries(getFile(GOLDFILE_UNSORTED));
Multimap<String, IdentifierDefinition> extractions_unsorted = evaluator.readExtractions(getFile(EXTRACTIONS_UNSORTED), gold);
ScoreSummary result = evaluator.evaluate(extractions_unsorted, gold);
Assert.assertEquals(new ScoreSummary(UNSORTED_TP, 0, UNSORTED_TOTAL_IDENTIFIERS - UNSORTED_TP, UNSORTED_TOTAL_EXTRACTIONS - UNSORTED_TP, 0), result);
}
}