package edu.stanford.nlp.naturalli;
import edu.stanford.nlp.util.Pair;
import java.util.*;
import static edu.stanford.nlp.naturalli.NaturalLogicRelation.*;
/**
* A collection of quantifiers. This is the exhaustive list of quantifiers our system knows about.
*
* @author Gabor Angeli
*/
public enum Operator {
// "All" quantifiers
ALL("all", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
EVERY("every", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
ANY("any", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
EACH("each", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
THE_LOT_OF("the lot of", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
ALL_OF("all of", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
EACH_OF("each of", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
FOR_ALL("for all", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
FOR_EVERY("for every", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
FOR_EACH("for each", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
EVERYONE("everyone", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
NUM("--num--", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"), // TODO check me
NUM_NUM("--num-- --num--", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"), // TODO check me
NUM_NUM_NUM("--num-- --num-- --num--", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"), // TODO check me
NUM_NUM_NUM_NUM("--num-- --num-- --num-- --num--", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"), // TODO check me
FEW("few", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"), // TODO check me
IMPLICIT_NAMED_ENTITY("__implicit_named_entity__", FORWARD_ENTAILMENT, "anti-additive", "multiplicative"),
// "No" quantifiers
NO("no", INDEPENDENCE, "anti-additive", "anti-additive"),
NEITHER("neither", INDEPENDENCE, "anti-additive", "anti-additive"),
NO_ONE("no one", INDEPENDENCE, "anti-additive", "anti-additive"),
NOBODY("nobody", INDEPENDENCE, "anti-additive", "anti-additive"),
UNARY_NO("no", INDEPENDENCE, "anti-additive"),
UNARY_NOT("not", INDEPENDENCE, "anti-additive"),
UNARY_NO_ONE("no one", INDEPENDENCE, "anti-additive"),
UNARY_NT("n't", INDEPENDENCE, "anti-additive"),
// A general quantifier for all "doubt"-like words
GENERAL_NEG_POLARITY("neg_polarity_trigger", INDEPENDENCE, "anti-additive"),
// "Some" quantifiers
SOME("some", FORWARD_ENTAILMENT, "additive", "additive"),
SEVERAL("several", FORWARD_ENTAILMENT, "additive", "additive"),
EITHER("either", FORWARD_ENTAILMENT, "additive", "additive"),
A("a", FORWARD_ENTAILMENT, "additive-multiplicative", "additive-multiplicative"),
THE("the", FORWARD_ENTAILMENT, "additive-multiplicative", "additive-multiplicative"),
LESS_THAN("less than --num--", FORWARD_ENTAILMENT, "additive", "additive"),
SOME_OF("some of", FORWARD_ENTAILMENT, "additive", "additive"),
ONE_OF("one of", FORWARD_ENTAILMENT, "additive", "additive"),
AT_LEAST("at least --num--", FORWARD_ENTAILMENT, "additive", "additive"),
A_FEW("a few", FORWARD_ENTAILMENT, "additive", "additive"),
AT_LEAST_A_FEW("at least a few", FORWARD_ENTAILMENT, "additive", "additive"),
THERE_BE("there be", FORWARD_ENTAILMENT, "additive", "additive"),
THERE_BE_A_FEW("there be a few", FORWARD_ENTAILMENT, "additive", "additive"),
THERE_EXIST("there exist", FORWARD_ENTAILMENT, "additive", "additive"),
NUM_OF("--num-- of", FORWARD_ENTAILMENT, "additive", "additive"),
// "Not All" quantifiers
NOT_ALL("not all", INDEPENDENCE, "additive", "anti-multiplicative"),
NOT_EVERY("not every", INDEPENDENCE, "additive", "anti-multiplicative"),
// "Most" quantifiers
// TODO(gabor) check these
MOST("most", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
MORE("more", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
MANY("many", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
ENOUGH("enough", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
MORE_THAN("more than __num_", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
LOTS_OF("lots of", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
PLENTY_OF("plenty of", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
HEAPS_OF("heap of", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
A_LOAD_OF("a load of", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
LOADS_OF("load of", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
TONS_OF("ton of", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
BOTH("both", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
JUST_NUM("just --num--", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
ONLY_NUM("only --num--", FORWARD_ENTAILMENT, "nonmonotone", "multiplicative"),
// Strange cases
AT_MOST_NUM("at most --num--", FORWARD_ENTAILMENT, "anti-additive", "anti-additive"),
;
public static final Set<String> GLOSSES = Collections.unmodifiableSet(new HashSet<String>() {{
for (Operator q : Operator.values()) {
add(q.surfaceForm);
}
}});
/**
* An ordered list of the known operators, by token length (descending). This ensures that we're matching the
* widest scoped operator.
*/
public static final List<Operator> valuesByLengthDesc = Collections.unmodifiableList(new ArrayList<Operator>(){{
for (Operator op : values()) {
add(op);
}
Collections.sort(this, (a, b) -> b.surfaceForm.split(" ").length - a.surfaceForm.split(" ").length);
}});
public final String surfaceForm;
public final Monotonicity subjMono;
public final MonotonicityType subjType;
public final Monotonicity objMono;
public final MonotonicityType objType;
public final NaturalLogicRelation deleteRelation;
Operator(String surfaceForm, NaturalLogicRelation deleteRelation, String subjMono, String objMono) {
this.surfaceForm = surfaceForm;
this.deleteRelation = deleteRelation;
Pair<Monotonicity, MonotonicityType> subj = monoFromString(subjMono);
this.subjMono = subj.first;
this.subjType = subj.second;
Pair<Monotonicity, MonotonicityType> obj = monoFromString(objMono);
this.objMono = obj.first;
this.objType = obj.second;
}
Operator(String surfaceForm, NaturalLogicRelation deleteRelation, String subjMono) {
this.surfaceForm = surfaceForm;
this.deleteRelation = deleteRelation;
Pair<Monotonicity, MonotonicityType> subj = monoFromString(subjMono);
this.subjMono = subj.first;
this.subjType = subj.second;
this.objMono = Monotonicity.INVALID;
this.objType = MonotonicityType.NONE;
}
public boolean isUnary() {
return objMono == Monotonicity.INVALID;
}
public static Pair<Monotonicity, MonotonicityType> monoFromString(String mono) {
switch (mono) {
case "nonmonotone": return Pair.makePair(Monotonicity.NONMONOTONE, MonotonicityType.NONE);
case "additive": return Pair.makePair(Monotonicity.MONOTONE, MonotonicityType.ADDITIVE);
case "multiplicative": return Pair.makePair(Monotonicity.MONOTONE, MonotonicityType.MULTIPLICATIVE);
case "additive-multiplicative": return Pair.makePair(Monotonicity.MONOTONE, MonotonicityType.BOTH);
case "anti-additive": return Pair.makePair(Monotonicity.ANTITONE, MonotonicityType.ADDITIVE);
case "anti-multiplicative": return Pair.makePair(Monotonicity.ANTITONE, MonotonicityType.MULTIPLICATIVE);
case "anti-additive-multiplicative": return Pair.makePair(Monotonicity.ANTITONE, MonotonicityType.BOTH);
default: throw new IllegalArgumentException("Unknown monotonicity: " + mono);
}
}
public static String monotonicitySignature(Monotonicity mono, MonotonicityType type) {
switch (mono) {
case MONOTONE:
switch (type) {
case NONE: return "nonmonotone";
case ADDITIVE: return "additive";
case MULTIPLICATIVE: return "multiplicative";
case BOTH: return "additive-multiplicative";
}
case ANTITONE:
switch (type) {
case NONE: return "nonmonotone";
case ADDITIVE: return "anti-additive";
case MULTIPLICATIVE: return "anti-multiplicative";
case BOTH: return "anti-additive-multiplicative";
}
case NONMONOTONE: return "nonmonotone";
}
throw new IllegalStateException("Unhandled case: " + mono + " and " + type);
}
@SuppressWarnings("UnusedDeclaration")
public static final Set<String> quantifierGlosses = Collections.unmodifiableSet(new HashSet<String>() {{
for (Operator operator : values()) {
add(operator.surfaceForm);
}
}});
public static Optional<Operator> fromString(String word) {
String wordToLowerCase = word.toLowerCase().replaceAll("[0-9]", "--num-- ").trim();
for (Operator candidate : Operator.values()) {
if (candidate.surfaceForm.equals(wordToLowerCase)) {
return Optional.of(candidate);
}
}
return Optional.empty();
}
}