package edu.uncc.cs.watsonsim.researchers; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import edu.stanford.nlp.util.Pair; import edu.uncc.cs.watsonsim.Answer; import edu.uncc.cs.watsonsim.Environment; import edu.uncc.cs.watsonsim.Passage; import edu.uncc.cs.watsonsim.Phrase; import edu.uncc.cs.watsonsim.Question; import edu.uncc.cs.watsonsim.nlp.ClueType; import edu.uncc.cs.watsonsim.nlp.DBPediaCandidateType; import edu.uncc.cs.watsonsim.nlp.SupportCandidateType; import edu.uncc.cs.watsonsim.nlp.Relatedness; public class TagLAT extends Researcher { private final DBPediaCandidateType dbpedia; private final Relatedness syn; public TagLAT(Environment env) { dbpedia = new DBPediaCandidateType(env); syn = new Relatedness(env); } public List<Answer> pull(Question q, List<Answer> answers) { return pull(q, answers, 0); } public List<Answer> pull(Question q, List<Answer> answers, int depth) { return question(q, chain.pull(q, answers), depth); } /** * Find the possible lexical types of a candidate, and label the answer. */ public List<Answer> question(Question q, List<Answer> answers, int depth) { int have_any_types = 0; int dbpedia_types = 0; int support_types = 0; List<Answer> suggestions = new ArrayList<>(); for (Answer a: answers) { // Handle DBPedia types a.lexical_types = dbpedia.viaDBPedia(a.text); for (String type: a.lexical_types) { a.log(this, "DBPedia says it's a %s", type); } if (a.lexical_types.isEmpty()) a.log(this, "DBPedia has no type information for it."); dbpedia_types += a.lexical_types.size(); // Handle Support types for (Passage p: a.passages) { List<Pair<String, String>> types = p.memo(SupportCandidateType::extract); for (Pair<String, String> name_and_type : types) { Phrase name = new Phrase(name_and_type.first); Phrase type = new Phrase(name_and_type.second); if (syn.implies(a, name)) { a.log(this, "Passage %s says it's a %s.", p.reference, type); a.lexical_types.add(type.text); support_types++; } else if (syn.implies(type, new Phrase(q.memo(ClueType::fromClue)))) { Answer suggestion = new Answer(name.text); suggestion.lexical_types = Arrays.asList(type.text); suggestion.log(this, "Found it's a %s, while reading about %s in %s", type, a, p.reference); if (!(suggestions.contains(suggestion) || answers.contains(suggestion))) { log.info("Suggesting " + name); suggestions.add(suggestion); } } } } if (!a.lexical_types.isEmpty()) have_any_types++; } // This is the chain magic: // We can pull the new suggestions through the pipeline and merge them! List<Answer> new_answers = new ArrayList<>(); if (!suggestions.isEmpty() && depth < 3) new_answers.addAll(pull(q, suggestions, depth+1)); new_answers.addAll(answers); //System.out.println(text + " could be any of " + types); log.info("Found " + (dbpedia_types+support_types) + " types for " + have_any_types + " candidates. ("+ support_types +" by reading) " + (answers.size() - have_any_types) + " candidates are unknown."); return new_answers; } }