package org.ggp.base.util.gdl.model.assignments; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import org.ggp.base.util.gdl.GdlUtils; import org.ggp.base.util.gdl.grammar.GdlConstant; import org.ggp.base.util.gdl.grammar.GdlSentence; import org.ggp.base.util.gdl.grammar.GdlVariable; import org.ggp.base.util.gdl.model.SentenceForm; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Maps; /** * Defines a {@link FunctionInfo} that can have values added to it (but * not removed from it) over time. This allows the functional * info to stay correct as new values are added with minimal * additional computation. * * Not thread-safe. */ public class MutableFunctionInfo implements AddibleFunctionInfo { private final SentenceForm form; private final List<Boolean> dependentSlots = new ArrayList<Boolean>(); private final List<Map<ImmutableList<GdlConstant>, GdlConstant>> valueMaps = Lists.newArrayList(); private MutableFunctionInfo(SentenceForm form) { this.form = form; for (int i = 0; i < form.getTupleSize(); i++) { dependentSlots.add(true); valueMaps.add(Maps.<ImmutableList<GdlConstant>, GdlConstant>newHashMap()); } } public static MutableFunctionInfo create(SentenceForm form) { return create(form, ImmutableSet.<GdlSentence>of()); } public static MutableFunctionInfo create(SentenceForm form, Collection<GdlSentence> initialSentences) { MutableFunctionInfo functionInfo = new MutableFunctionInfo(form); for (GdlSentence sentence : initialSentences) { functionInfo.addTuple(GdlUtils.getTupleFromGroundSentence(sentence)); } return functionInfo; } @Override public SentenceForm getSentenceForm() { return form; } @Override public void addTuple(List<GdlConstant> sentenceTuple) { if (sentenceTuple.size() != form.getTupleSize()) { throw new IllegalArgumentException(); } //For each slot... for (int i = 0; i < sentenceTuple.size(); i++) { if (dependentSlots.get(i)) { //Either add to that entry, or invalidate the slot Map<ImmutableList<GdlConstant>, GdlConstant> valueMap = valueMaps.get(i); List<GdlConstant> lookupTuple = Lists.newArrayList(sentenceTuple); lookupTuple.remove(i); GdlConstant curValue = valueMap.get(lookupTuple); GdlConstant newValue = sentenceTuple.get(i); if (curValue == null) { //Just add to the map valueMap.put(ImmutableList.copyOf(lookupTuple), newValue); } else { //If this isn't the existing sentence, invalidate this slot if (curValue != newValue) { dependentSlots.set(i, false); valueMaps.set(i, ImmutableMap.<ImmutableList<GdlConstant>, GdlConstant>of()); } } } } } @Override public List<Boolean> getDependentSlots() { return Collections.unmodifiableList(dependentSlots); } @Override public Set<GdlVariable> getProducibleVars(GdlSentence sentence) { return FunctionInfos.getProducibleVars(this, sentence); } @Override public Map<ImmutableList<GdlConstant>, GdlConstant> getValueMap(int varIndex) { return Collections.unmodifiableMap(valueMaps.get(varIndex)); } @Override public void addSentence(GdlSentence sentence) { addTuple(GdlUtils.getTupleFromGroundSentence(sentence)); } @Override public String toString() { return "MutableFunctionInfo [form=" + form + ", dependentSlots=" + dependentSlots + ", valueMaps=" + valueMaps + "]"; } }