package edu.stanford.nlp.sempre.tables.lambdadcs; import java.util.*; import edu.stanford.nlp.sempre.*; import edu.stanford.nlp.sempre.AggregateFormula.Mode; import fig.basic.LispTree; import fig.basic.MapUtils; import fig.basic.Pair; public class ExplicitPairList implements PairList { // Following LambdaDCS convention, pair (v, k) means k maps to v. protected final List<Pair<Value, Value>> pairs; protected final Map<Value, UnaryDenotation> mapping; protected final Map<Value, UnaryDenotation> reverseMapping; // ============================================================ // Constructors // ============================================================ public ExplicitPairList() { pairs = Collections.emptyList(); mapping = Collections.emptyMap(); reverseMapping = Collections.emptyMap(); } public ExplicitPairList(Value key, Value value) { pairs = Collections.singletonList(new Pair<>(value, key)); mapping = Collections.singletonMap(key, new ExplicitUnaryDenotation(value)); reverseMapping = Collections.singletonMap(value, new ExplicitUnaryDenotation(key)); } public ExplicitPairList(Pair<Value, Value> pair) { pairs = Collections.singletonList(pair); mapping = Collections.singletonMap(pair.getSecond(), new ExplicitUnaryDenotation(pair.getFirst())); reverseMapping = Collections.singletonMap(pair.getFirst(), new ExplicitUnaryDenotation(pair.getSecond())); } public ExplicitPairList(List<Pair<Value, Value>> pairs) { this.pairs = pairs; Map<Value, List<Value>> mappingBuilder = new HashMap<>(), reverseMappingBuilder = new HashMap<>(); for (Pair<Value, Value> pair : pairs) { MapUtils.addToList(mappingBuilder, pair.getSecond(), pair.getFirst()); MapUtils.addToList(reverseMappingBuilder, pair.getFirst(), pair.getSecond()); } mapping = new HashMap<>(); for (Map.Entry<Value, List<Value>> entry : mappingBuilder.entrySet()) mapping.put(entry.getKey(), new ExplicitUnaryDenotation(entry.getValue())); reverseMapping = new HashMap<>(); for (Map.Entry<Value, List<Value>> entry : reverseMappingBuilder.entrySet()) reverseMapping.put(entry.getKey(), new ExplicitUnaryDenotation(entry.getValue())); } public <T extends Collection<Value>> ExplicitPairList(Map<Value, T> keyToValues) { pairs = new ArrayList<>(); Map<Value, List<Value>> reverseMappingBuilder = new HashMap<>(); for (Map.Entry<Value, T> entry : keyToValues.entrySet()) { for (Value value : entry.getValue()) { pairs.add(new Pair<>(value, entry.getKey())); MapUtils.addToList(reverseMappingBuilder, value, entry.getKey()); } } mapping = new HashMap<>(); for (Map.Entry<Value, T> entry : keyToValues.entrySet()) mapping.put(entry.getKey(), new ExplicitUnaryDenotation(entry.getValue())); reverseMapping = new HashMap<>(); for (Map.Entry<Value, List<Value>> entry : reverseMappingBuilder.entrySet()) reverseMapping.put(entry.getKey(), new ExplicitUnaryDenotation(entry.getValue())); } // ============================================================ // Representation // ============================================================ @Override public String toString() { return toLispTree().toString(); } protected static final LispTree NULL_LEAF = LispTree.proto.newLeaf(null); @Override public LispTree toLispTree() { LispTree tree = LispTree.proto.newList(); for (Pair<Value, Value> pair : pairs) { Value first = pair.getFirst(), second = pair.getSecond(); tree.addChild(LispTree.proto.newList( first == null ? NULL_LEAF : first.toLispTree(), second == null ? NULL_LEAF : second.toLispTree())); } return tree; } @Override public PairListValue toValue() { PairListValue result = new PairListValue(pairs); if (LambdaDCSExecutor.opts.sortResults) result = result.getSorted(); return result; } // ============================================================ // Getter // ============================================================ @Override public UnaryDenotation domain() { return new ExplicitUnaryDenotation(mapping.keySet()); } @Override public UnaryDenotation range() { return new ExplicitUnaryDenotation(reverseMapping.keySet()); } @Override public UnaryDenotation get(Value key) { UnaryDenotation values = mapping.get(key); if (values == null) values = mapping.get(null); return values == null ? UnaryDenotation.EMPTY : values; } @Override public UnaryDenotation inverseGet(Value value) { UnaryDenotation keys = reverseMapping.get(value); return keys == null ? UnaryDenotation.EMPTY : keys; } // ============================================================ // Operations // ============================================================ @Override public PairList aggregate(Mode mode) { Map<Value, UnaryDenotation> aggregated = new HashMap<>(); for (Map.Entry<Value, UnaryDenotation> entry : mapping.entrySet()) { aggregated.put(entry.getKey(), entry.getValue().aggregate(mode)); } if (mode == Mode.count && !aggregated.containsKey(null)) aggregated.put(null, UnaryDenotation.ZERO); return new ExplicitPairList(aggregated); } @Override public PairList filter(UnaryDenotation upperBound, UnaryDenotation domainUpperBound) { return explicitlyFilter(upperBound, domainUpperBound); } @Override public ExplicitPairList reverse() { List<Pair<Value, Value>> reversed = new ArrayList<>(); for (Pair<Value, Value> pair : pairs) { reversed.add(new Pair<>(pair.getSecond(), pair.getFirst())); } return new ExplicitPairList(reversed); } @Override public UnaryDenotation joinOnKey(UnaryDenotation keys) { List<Value> values = new ArrayList<>(); for (Map.Entry<Value, UnaryDenotation> entry : mapping.entrySet()) { if (keys.contains(entry.getKey())) values.addAll(entry.getValue()); } return new ExplicitUnaryDenotation(values); } @Override public UnaryDenotation joinOnValue(UnaryDenotation values) { List<Value> keys = new ArrayList<>(); for (Map.Entry<Value, UnaryDenotation> entry : reverseMapping.entrySet()) { if (values.contains(entry.getKey())) keys.addAll(entry.getValue()); } return new ExplicitUnaryDenotation(keys); } @Override public ExplicitPairList explicitlyFilterOnKey(UnaryDenotation keys) { List<Pair<Value, Value>> filtered = new ArrayList<>(); for (Pair<Value, Value> pair : pairs) { if (keys.contains(pair.getSecond())) filtered.add(pair); } return new ExplicitPairList(filtered); } @Override public ExplicitPairList explicitlyFilterOnValue(UnaryDenotation values) { List<Pair<Value, Value>> filtered = new ArrayList<>(); for (Pair<Value, Value> pair : pairs) { if (values.contains(pair.getFirst())) filtered.add(pair); } return new ExplicitPairList(filtered); } public ExplicitPairList explicitlyFilter(UnaryDenotation values, UnaryDenotation keys) { List<Pair<Value, Value>> filtered = new ArrayList<>(); for (Pair<Value, Value> pair : pairs) { if (values.contains(pair.getFirst()) && keys.contains(pair.getSecond())) filtered.add(pair); } return new ExplicitPairList(filtered); } }