}
}
//See if any of the functions are applicable
Set<Integer> functions = functionsHavingDependencies.get(dependencySetToUse);
int functionToUse = -1;
GdlVariable varProduced = null;
for (int function : functions) {
GdlSentence functionalSentence = functionalSentences.get(function);
FunctionInfo functionInfo = functionalSentencesInfo.get(function);
Set<GdlVariable> producibleVars = functionInfo.getProducibleVars(functionalSentence);
producibleVars.removeAll(dependencySetToUse);
producibleVars.removeAll(varOrdering);
if(!producibleVars.isEmpty()) {
functionToUse = function;
varProduced = producibleVars.iterator().next();
break;
}
}
if(functionToUse == -1) {
//None of these functions were actually useful now?
//Dump the dependency set
functionsHavingDependencies.remove(dependencySetToUse);
} else {
//Apply the function
//1) Add the remaining dependencies as iterated variables
for(GdlVariable var : dependencySetToUse) {
varOrdering.add(var);
functionalConjunctIndices.add(-1);
varSources.add(-1);
}
//2) Add the function's produced variable (varProduced)
varOrdering.add(varProduced);
functionalConjunctIndices.add(functionToUse);
varSources.add(-1);
//3) Remove all vars added this way from all dependency sets
Set<GdlVariable> addedVars = new HashSet<GdlVariable>();
addedVars.addAll(dependencySetToUse);
addedVars.add(varProduced);
//Tricky, because we have to merge sets
//Easier to use a new map
Map<Set<GdlVariable>, Set<Integer>> newFunctionsHavingDependencies = new HashMap<Set<GdlVariable>, Set<Integer>>();
for(Entry<Set<GdlVariable>, Set<Integer>> entry : functionsHavingDependencies.entrySet()) {
Set<GdlVariable> newKey = new HashSet<GdlVariable>(entry.getKey());
newKey.removeAll(addedVars);
if(!newFunctionsHavingDependencies.containsKey(newKey))
newFunctionsHavingDependencies.put(newKey, new HashSet<Integer>());
newFunctionsHavingDependencies.get(newKey).addAll(entry.getValue());
}
functionsHavingDependencies = newFunctionsHavingDependencies;
//4) Remove this function from the lists?
for(Set<Integer> functionSet : functionsHavingDependencies.values())
functionSet.remove(functionToUse);
}
}
//Now we need to actually return the ordering in a list
//Here's the quick way to do that...
//(since we've added all the new stuff to ourself already)
return Collections.singletonList(new IterationOrderCandidate(this));
} else {
//Let's try a new technique for restricting the space of possibilities...
//We already have an ordering on the functions
//Let's try to constrain things to that order
//Namely, if i<j and constant form j is already used as a function,
//we cannot use constant form i UNLESS constant form j supplies
//as its variable something used by constant form i.
//We might also try requiring that c.f. i NOT provide a variable
//used by c.f. j, though there may be multiple possibilities as
//to what it could provide.
int lastFunctionUsedIndex = -1;
if (!functionalConjunctIndices.isEmpty()) {
lastFunctionUsedIndex = Collections.max(functionalConjunctIndices);
}
Set<GdlVariable> varsProducedByFunctions = new HashSet<GdlVariable>();
for (int i = 0; i < functionalConjunctIndices.size(); i++) {
if (functionalConjunctIndices.get(i) != -1) {
varsProducedByFunctions.add(varOrdering.get(i));
}
}
for (int i = 0; i < functionalSentencesInfo.size(); i++) {
GdlSentence functionalSentence = functionalSentences.get(i);
FunctionInfo functionInfo = functionalSentencesInfo.get(i);
if (i < lastFunctionUsedIndex) {
//We need to figure out whether i could use any of the
//vars we're producing with functions
//TODO: Try this with a finer grain
//i.e., see if i needs a var from a function that is after
//it, not one that might be before it
List<GdlVariable> varsInSentence = GdlUtils.getVariables(functionalSentence);
if (Collections.disjoint(varsInSentence, varsProducedByFunctions)) {
continue;
}
}
//What is the best variable to grab from this form, if there are any?
GdlVariable bestVariable = getBestVariable(functionalSentence, functionInfo);
if (bestVariable == null) {
continue;
}
IterationOrderCandidate newCandidate =
new IterationOrderCandidate(this, functionalSentence, i, bestVariable);