//For does/true, make nodes based on input/base, if available
if(usingInput && form.getName().equals(DOES)) {
//Add only those propositions for which there is a corresponding INPUT
SentenceForm inputForm = form.withName(INPUT);
for (GdlSentence inputSentence : constantChecker.getTrueSentences(inputForm)) {
GdlSentence doesSentence = GdlPool.getRelation(DOES, inputSentence.getBody());
Proposition prop = new Proposition(doesSentence);
components.put(doesSentence, prop);
}
return;
}
if(usingBase && form.getName().equals(TRUE)) {
SentenceForm baseForm = form.withName(BASE);
for (GdlSentence baseSentence : constantChecker.getTrueSentences(baseForm)) {
GdlSentence trueSentence = GdlPool.getRelation(TRUE, baseSentence.getBody());
Proposition prop = new Proposition(trueSentence);
components.put(trueSentence, prop);
}
return;
}
Map<GdlSentence, Set<Component>> inputsToOr = new HashMap<GdlSentence, Set<Component>>();
for(GdlRule rule : rules) {
Assignments assignments = AssignmentsFactory.getAssignmentsForRule(rule, model, functionInfoMap, completedSentenceFormValues);
//Calculate vars in live (non-constant, non-distinct) conjuncts
Set<GdlVariable> varsInLiveConjuncts = getVarsInLiveConjuncts(rule, constantChecker.getConstantSentenceForms());
varsInLiveConjuncts.addAll(GdlUtils.getVariables(rule.getHead()));
Set<GdlVariable> varsInRule = new HashSet<GdlVariable>(GdlUtils.getVariables(rule));
boolean preventDuplicatesFromConstants =
(varsInRule.size() > varsInLiveConjuncts.size());
//Do we just pass those to the Assignments class in that case?
for(AssignmentIterator asnItr = assignments.getIterator(); asnItr.hasNext(); ) {
Map<GdlVariable, GdlConstant> assignment = asnItr.next();
if(assignment == null) continue; //Not sure if this will ever happen
ConcurrencyUtils.checkForInterruption();
GdlSentence sentence = CommonTransforms.replaceVariables(rule.getHead(), assignment);
//Now we go through the conjuncts as before, but we wait to hook them up.
List<Component> componentsToConnect = new ArrayList<Component>(rule.arity());
for(GdlLiteral literal : rule.getBody()) {
if(literal instanceof GdlSentence) {
//Get the sentence post-substitutions
GdlSentence transformed = CommonTransforms.replaceVariables((GdlSentence) literal, assignment);
//Check for constant-ness
SentenceForm conjunctForm = model.getSentenceForm(transformed);
if(constantChecker.isConstantForm(conjunctForm)) {
if(!constantChecker.isTrueConstant(transformed)) {
List<GdlVariable> varsToChange = getVarsInConjunct(literal);
asnItr.changeOneInNext(varsToChange, assignment);
componentsToConnect.add(null);
}
continue;
}
Component conj = components.get(transformed);
//If conj is null and this is a sentence form we're still handling,
//hook up to a temporary sentence form
if(conj == null) {
conj = temporaryComponents.get(transformed);
}
if(conj == null && SentenceModelUtils.inSentenceFormGroup(transformed, recursionForms)) {
//Set up a temporary component
Proposition tempProp = new Proposition(transformed);
temporaryComponents.put(transformed, tempProp);
conj = tempProp;
}
//Let's say this is false; we want to backtrack and change the right variable
if(conj == null || isThisConstant(conj, falseComponent)) {
List<GdlVariable> varsInConjunct = getVarsInConjunct(literal);
asnItr.changeOneInNext(varsInConjunct, assignment);
//These last steps just speed up the process
//telling the factory to ignore this rule
componentsToConnect.add(null);
continue; //look at all the other restrictions we'll face
}
componentsToConnect.add(conj);
} else if(literal instanceof GdlNot) {
//Add a "not" if necessary
//Look up the negation
GdlSentence internal = (GdlSentence) ((GdlNot) literal).getBody();
GdlSentence transformed = CommonTransforms.replaceVariables(internal, assignment);
//Add constant-checking here...
SentenceForm conjunctForm = model.getSentenceForm(transformed);
if(constantChecker.isConstantForm(conjunctForm)) {
if(constantChecker.isTrueConstant(transformed)) {
List<GdlVariable> varsToChange = getVarsInConjunct(literal);
asnItr.changeOneInNext(varsToChange, assignment);
componentsToConnect.add(null);
}
continue;
}
Component conj = negations.get(transformed);
if(isThisConstant(conj, falseComponent)) {
//We need to change one of the variables inside
List<GdlVariable> varsInConjunct = getVarsInConjunct(internal);
asnItr.changeOneInNext(varsInConjunct, assignment);
//ignore this rule
componentsToConnect.add(null);
continue;
}
if(conj == null) {
conj = temporaryNegations.get(transformed);
}
//Check for the recursive case:
if(conj == null && SentenceModelUtils.inSentenceFormGroup(transformed, recursionForms)) {
Component positive = components.get(transformed);
if(positive == null) {
positive = temporaryComponents.get(transformed);
}
if(positive == null) {
//Make the temporary proposition
Proposition tempProp = new Proposition(transformed);
temporaryComponents.put(transformed, tempProp);
positive = tempProp;
}
//Positive is now set and in temporaryComponents
//Evidently, wasn't in temporaryNegations
//So we add the "not" gate and set it in temporaryNegations
Not not = new Not();
//Add positive as input
not.addInput(positive);
positive.addOutput(not);
temporaryNegations.put(transformed, not);
conj = not;
}
if(conj == null) {
Component positive = components.get(transformed);
//No, because then that will be attached to "negations", which could be bad
if(positive == null) {
//So the positive can't possibly be true (unless we have recurstion)
//and so this would be positive always
//We want to just skip this conjunct, so we continue to the next
continue; //to the next conjunct
}
//Check if we're sharing a component with another sentence with a negation
//(i.e. look for "nots" in our outputs and use those instead)
Not existingNotOutput = getNotOutput(positive);
if(existingNotOutput != null) {
componentsToConnect.add(existingNotOutput);
negations.put(transformed, existingNotOutput);
continue; //to the next conjunct
}
Not not = new Not();
not.addInput(positive);
positive.addOutput(not);
negations.put(transformed, not);
conj = not;
}
componentsToConnect.add(conj);
} else if(literal instanceof GdlDistinct) {
//Already handled; ignore
} else {
throw new RuntimeException("Unwanted GdlLiteral type");
}
}
if(!componentsToConnect.contains(null)) {
//Connect all the components
Proposition andComponent = new Proposition(TEMP);
andify(componentsToConnect, andComponent, trueComponent);
if(!isThisConstant(andComponent, falseComponent)) {
if(!inputsToOr.containsKey(sentence))
inputsToOr.put(sentence, new HashSet<Component>());
inputsToOr.get(sentence).add(andComponent);
//We'll want to make sure at least one of the non-constant
//components is changing
if(preventDuplicatesFromConstants) {
asnItr.changeOneInNext(varsInLiveConjuncts, assignment);
}
}
}
}
}
//At the end, we hook up the conjuncts
for(Entry<GdlSentence, Set<Component>> entry : inputsToOr.entrySet()) {
ConcurrencyUtils.checkForInterruption();
GdlSentence sentence = entry.getKey();
Set<Component> inputs = entry.getValue();
Set<Component> realInputs = new HashSet<Component>();
for(Component input : inputs) {
if(input instanceof Constant || input.getInputs().size() == 0) {
realInputs.add(input);