/**
* SPINdle (version 2.2.2)
* Copyright (C) 2009-2012 NICTA Ltd.
*
* This file is part of SPINdle project.
*
* SPINdle is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SPINdle is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with SPINdle. If not, see <http://www.gnu.org/licenses/>.
*
* @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory
*/
package spindle.engine.sdl;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.logging.Level;
import com.app.utils.TextUtilities;
import com.app.utils.Utilities.ProcessStatus;
import spindle.core.dom.Conclusion;
import spindle.core.dom.ConclusionType;
import spindle.core.dom.Literal;
import spindle.core.dom.Rule;
import spindle.core.dom.RuleType;
import spindle.core.dom.TheoryException;
import spindle.engine.ReasoningEngineBase;
import spindle.engine.ReasoningEngineException;
import spindle.sys.AppConst;
import spindle.sys.AppFeatureConst;
import spindle.sys.Conf;
import spindle.tools.analyser.TheoryAnalyser;
import spindle.tools.explanation.RuleInferenceStatus;
/**
* SDL Reasoning Engine.
* <p>
* This reasoning engine is based on the algorithm presented in:
* <ul>
* <li>Maher, M.J. (2001) Propositional Defeasible Logic has Linear Complexity, <i>Theory and Practice of Logic
* Programming</i>, 1:6:691-711, Cambridge University Press</li>
* </ul>
* </p>
*
* @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory
* @see SdlReasoningEngine2
* @since version 1.0.0
* @version Last modified 2012.07.21
*/
public class SdlReasoningEngine extends ReasoningEngineBase {
/**
* pending conclusions set
*/
protected Deque<Conclusion>[] pendingConclusions = null;
/**
* Used to hold possibly conflicting conclusions in the theory temporary.
* That is in the condition that when [+D q] is concluded from one rule,
* another rule containing [+D -q] is still pending to process.
* Conclusion will be added to the conclusions set only when all its related
* consequence are computed
*/
protected Map<Conclusion, Set<String>>[] ambiguousConclusions = null;
/**
* Used to hold the set of generated conclusions.
*/
protected Map<Literal, Map<ConclusionType, Conclusion>> conclusions = null;
protected List<Set<Literal>> sccLiteralsGroups = null;
protected Set<Conclusion> unresolveableConclusionsSet = null;
protected boolean theoryWithLoops = true;
public SdlReasoningEngine() {
super();
}
@SuppressWarnings("unchecked")
@Override
protected void initialize() throws ReasoningEngineException {
pendingConclusions = new ArrayDeque[2];
ambiguousConclusions = new TreeMap[2];
unresolveableConclusionsSet = new TreeSet<Conclusion>();
sccLiteralsGroups = null;
for (int i = 0; i < 2; i++) {
pendingConclusions[i] = new ArrayDeque<Conclusion>(AppConst.INITIAL_PENDING_CONCLUSIONS_QUEUE_CAPACITY);
ambiguousConclusions[i] = new TreeMap<Conclusion, Set<String>>();
}
conclusions = new TreeMap<Literal, Map<ConclusionType, Conclusion>>();
duplicateStrictRulesToDefeasibleRules();
strictRules = theory.getRules(RuleType.STRICT);
defeasibleRules = theory.getRules(RuleType.DEFEASIBLE);
theoryWithLoops = true;
if (!AppConst.isDeploy) {
logMessage(Level.INFO, 0, "=== SdlReasoningEngine.initialize - theory@start - start ===");
logMessage(Level.INFO, 0, null, theory);
logMessage(Level.INFO, 0, "=== SdlReasoningEngine.initialize - theory@start - end ===");
}
try {
generateInitialPendingConclusions();
} catch (ReasoningEngineException e) {
throw e;
} catch (Exception e) {
throw new ReasoningEngineException(getClass(), e);
}
}
@Override
protected void generateConclusions() throws ReasoningEngineException {
Conclusion conclusion = null;
if (!AppConst.isDeploy) printEngineStatus("generateConclusions - start");
try {
while ((conclusion = getNextPendingConclusion()) != null) {
if (isConclusionExist(conclusion)) continue;
logMessage(Level.FINE, 0, "generate conclusion for ", conclusion);
addConclusion(conclusion);
switch (conclusion.getConclusionType()) {
case DEFINITE_PROVABLE:
generateConclusions_definiteProvable(conclusion.getLiteral());
break;
case DEFINITE_NOT_PROVABLE:
generateConclusions_definiteNotProvable(conclusion.getLiteral());
break;
case DEFEASIBLY_PROVABLE:
generateConclusions_defeasiblyProvable(conclusion.getLiteral());
break;
case DEFEASIBLY_NOT_PROVABLE:
generateConclusions_defeasiblyNotProvable(conclusion.getLiteral());
break;
default:
}
if (!AppConst.isDeploy) printEngineStatus("generateConclusions-after inflencing with [" + conclusion + "]");
}
} catch (ReasoningEngineException e) {
throw e;
} catch (Exception e) {
throw new ReasoningEngineException(getClass(), e);
} finally{
if (!AppConst.isDeploy) printEngineStatus("generateConclusions - finally");
}
}
@Override
protected void terminate() throws ReasoningEngineException {
if (!AppConst.isDeploy) printEngineStatus("terminate");
if (AppFeatureConst.isVerifyConclusionsAfterInference) conclusions = verifyConclusions(conclusions);
setConclusion(conclusions);
// Map<Literal, Map<ConclusionType, Conclusion>> dummyConclusions = transformConclusions(conclusions);
//
// if (AppFeatureConst.isVerifyConclusionsAfterInference) dummyConclusions = verifyConclusions(dummyConclusions);
// setConclusion(dummyConclusions);
}
// private Map<Literal,Map<ConclusionType,Conclusion>>transformConclusions(Map<ConclusionType,Map<Literal,Conclusion>>conclusions){
// Map<Literal,Map<ConclusionType,Conclusion>>newConclusions=new TreeMap<Literal,Map<ConclusionType,Conclusion>>();
// for (Entry<ConclusionType,Map<Literal,Conclusion>> conclusionTypeEntry:conclusions.entrySet()){
// for (Entry<Literal,Conclusion>literalEntry:conclusionTypeEntry.getValue().entrySet()){
// Literal l=literalEntry.getKey();
// Conclusion c=literalEntry.getValue();
// ConclusionType ct=c.getConclusionType();
//
// Map<ConclusionType,Conclusion>newConclusionEntry=newConclusions.get(l);
// if (null==newConclusionEntry){
// newConclusionEntry=new TreeMap<ConclusionType,Conclusion>();
// newConclusions.put(l,newConclusionEntry);
// }
// newConclusionEntry.put( ct,c);
// }
// }
// return newConclusions;
// }
protected ProcessStatus generateInitialPendingConclusions() throws ReasoningEngineException, TheoryException {
// literals appeared in strict rule with empty body are definitely provable
// literals appeared in defeasible rule with empty body are tentatively provable
logMessage(Level.FINE, 0, "=== SdlReasoningEngine.generateInitialPendingConclusions - start ===");
Set<Literal> unprovedStrictRuleLiterals = new TreeSet<Literal>(theory.getAllLiteralsInRules());
Set<Literal> unprovedDefeasibleRuleLiterals = new TreeSet<Literal>(theory.getAllLiteralsInRules());
Set<String> rulesToDelete = new TreeSet<String>();
logMessage(Level.FINER, 1, "=== +ve set - start ===");
Set<String> rulesToRemove = new TreeSet<String>();
Map<Conclusion, Set<String>> tempPosDefiniteConclusionSet = new TreeMap<Conclusion, Set<String>>();
Map<Conclusion, Set<String>> tempPosDefeasibleConclusionSet = new TreeMap<Conclusion, Set<String>>();
Set<String> ruleSet = null;
for (Rule rule : theory.getFactsAndAllRules().values()) {
Literal literal = rule.getHeadLiterals().get(0);
switch (rule.getRuleType()) {
case STRICT:
if (rule.isEmptyBody()) {
Conclusion conclusion = new Conclusion(ConclusionType.DEFINITE_PROVABLE, literal);
addRecord(conclusion);
ruleSet = tempPosDefiniteConclusionSet.get(conclusion);
if (null == ruleSet) {
ruleSet = new TreeSet<String>();
tempPosDefiniteConclusionSet.put(conclusion, ruleSet);
}
ruleSet.add(rule.getOriginalLabel());
rulesToRemove.add(rule.getLabel());
}
unprovedStrictRuleLiterals.remove(literal);
break;
case DEFEASIBLE:
if (rule.isEmptyBody()) {
Conclusion conclusion = new Conclusion(ConclusionType.DEFEASIBLY_PROVABLE, literal);
addRecord(conclusion);
ruleSet = tempPosDefeasibleConclusionSet.get(conclusion);
if (null == ruleSet) {
ruleSet = new TreeSet<String>();
tempPosDefeasibleConclusionSet.put(conclusion, ruleSet);
}
ruleSet.add(rule.getOriginalLabel());
rulesToRemove.add(rule.getLabel());
}
unprovedDefeasibleRuleLiterals.remove(literal);
break;
default:
}
}
removeRules(rulesToRemove);
if (!AppConst.isDeploy) {
printPendingConclusionSet(unprovedStrictRuleLiterals, unprovedDefeasibleRuleLiterals, tempPosDefiniteConclusionSet.keySet(),tempPosDefeasibleConclusionSet.keySet());
}
TreeSet<Literal> tempPosDefiniteConclusions =extractLiteralsFromConclusions( tempPosDefiniteConclusionSet.keySet());
TreeSet<Literal> tempPosDefeasibleConclusions =extractLiteralsFromConclusions( tempPosDefeasibleConclusionSet.keySet());
for (Entry<Conclusion, Set<String>> entry : tempPosDefiniteConclusionSet.entrySet()) {
Conclusion conclusion = entry.getKey();
Set<String> ruleLabels = entry.getValue();
boolean ambiguousExist = false, pos = true;
Literal literal = conclusion.getLiteral();
Set<Literal> conflictLiterals = getConflictLiterals(literal);
// switch (conclusion.getConclusionType()) {
// case DEFINITE_PROVABLE:
ambiguousExist = isTempConclusionExist(conflictLiterals, tempPosDefiniteConclusions);//, ConclusionType.DEFINITE_PROVABLE);
if (!ambiguousExist) ambiguousExist = containsUnprovedRuleInTheory(conflictLiterals, RuleType.STRICT);
if (ambiguousExist) {
logMessage(Level.FINER, 1, "==> generateInitialPendingConclusions: ==> add (+D Ambiguous)", literal);
addAmbiguousConclusion(conclusion, ruleLabels);
} else {
if (isRecordExist(conflictLiterals, ConclusionType.DEFINITE_PROVABLE)) pos = false;
if (isRecordExist(literal, ConclusionType.DEFINITE_NOT_PROVABLE)) pos = false;
logMessage(Level.FINEST, 1, "02, ambiguousExist=", ambiguousExist, ", pos=", pos);
if (pos) {
newLiteralFind_definiteProvable(literal, false);
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.APPICABLE);
} else {
newLiteralFind_definiteNotProvable(literal, false);
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.DISCARDED);
}
}
// break;
}
for (Entry<Conclusion, Set<String>> entry : tempPosDefeasibleConclusionSet.entrySet()) {
Conclusion conclusion=entry.getKey();
Set<String>ruleLabels=entry.getValue();
boolean ambiguousExist = false, pos = true;
Literal literal = conclusion.getLiteral();
Set<Literal> conflictLiterals = getConflictLiterals(literal);
// case DEFEASIBLY_PROVABLE:
ambiguousExist = isTempConclusionExist(conflictLiterals, tempPosDefeasibleConclusions);//, ConclusionType.DEFEASIBLY_PROVABLE);
if (!ambiguousExist) ambiguousExist = containsUnprovedRuleInTheory(conflictLiterals, RuleType.DEFEASIBLE);
if (ambiguousExist) {
logMessage(Level.FINER, 1, "==> generateInitialPendingConclusions: ==> add (+d Ambiguous)", literal);
addAmbiguousConclusion(conclusion, ruleLabels);
} else {
if (isRecordExist(conflictLiterals, ConclusionType.DEFEASIBLY_PROVABLE)) pos = false;
if (isRecordExist(literal, ConclusionType.DEFEASIBLY_NOT_PROVABLE)) pos = false;
logMessage(Level.FINEST, 1, "02, ambiguousExist=", ambiguousExist, ", pos=", pos);
if (pos) {
addPendingConclusion(conclusion);
newLiteralFind_defeasiblyProvable(literal, false);
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.APPICABLE);
} else {
Conclusion c = new Conclusion(ConclusionType.DEFEASIBLY_NOT_PROVABLE, literal);
addPendingConclusion(c);
newLiteralFind_defeasiblyNotProvable(literal, false);
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.DISCARDED);
}
}
// break;
// default:
}
logMessage(Level.FINER, 1, "=== +ve set - end ===");
// literals cannot be resolved using all rules are defeasibly not provable
logMessage(Level.FINER, 1, "=== -df set - start ===");
for (Literal literal : unprovedDefeasibleRuleLiterals) {
logMessage(Level.FINEST, 2, "rule.getLiteralList()(NOT_DEFEASIBLE)=", literal);
Conclusion conclusion = new Conclusion(ConclusionType.DEFEASIBLY_NOT_PROVABLE, literal);
if (!unresolveableConclusionsSet.contains(conclusion)) {
addPendingConclusion(conclusion);
addRecord(conclusion);
newLiteralFind_defeasiblyNotProvable(literal, false);
addInapplicableLiteralsBeforeInference(literal, ConclusionType.DEFEASIBLY_NOT_PROVABLE);
}
}
logMessage(Level.FINER, 1, "=== -df set - end ===");
// literals that do not exist in strict rule or
// literals cannot be resolved using only strict rules are definite not provable
logMessage(Level.FINER, 1, "=== -Df set - start ===");
for (Literal literal : unprovedStrictRuleLiterals) {
newLiteralFind_definiteNotProvable(literal, false);
addInapplicableLiteralsBeforeInference(literal, ConclusionType.DEFINITE_NOT_PROVABLE);
}
logMessage(Level.FINER, 1, "=== -Df set - end ===");
logMessage(Level.FINE, 0, "=== SdlReasoningEngine.generateInitialPendingConclusions - end ===");
removeRules(rulesToDelete);
return ProcessStatus.SUCCESS;
}
protected ProcessStatus generateConclusions_definiteProvable(final Literal literal) throws ReasoningEngineException, TheoryException {
logMessage(Level.FINER, 0, "=== generate inference: definite provable: ", literal);
Set<String> rulesToDelete = new TreeSet<String>();
Set<Rule> rulesModified = theory.removeBodyLiteralFromRules(literal, null);
if (rulesModified.size() == 0) return ProcessStatus.SUCCESS;
for (Rule rule : rulesModified) {
logMessage(Level.FINER, 1, null, literal, ": rule=", rule, ", is empty body=" + rule.isEmptyBody());
if (rule.isEmptyBody()) {
logMessage(Level.FINEST, 2, "remove rule:", rule.getLabel());
if (!AppConst.isDeploy) logMessage(Level.FINER, 2, null, theory);
rulesToDelete.add(rule.getLabel());
Literal headLiteral = rule.getHeadLiterals().get(0);
Set<Literal> conflictLiterals = getConflictLiterals(headLiteral);
switch (rule.getRuleType()) {
case STRICT:
logMessage(Level.FINER, 1, "==> ", literal, " (strict)");
if (containsUnprovedRuleInTheory(conflictLiterals, RuleType.STRICT)) {
logMessage(Level.FINER, 2, "==>1.1 generateConclusions_definiteProvable: ==> add ambiguous (+D)", headLiteral);
Conclusion conclusion = new Conclusion(ConclusionType.DEFINITE_PROVABLE, headLiteral);
addRecord(conclusion);
addAmbiguousConclusion(conclusion, rule.getOriginalLabel());
} else {
boolean chk1 = isAmbiguousConclusionExist(headLiteral, ConclusionType.DEFINITE_NOT_PROVABLE);
boolean chk2 = isAmbiguousConclusionExist(conflictLiterals, ConclusionType.DEFINITE_PROVABLE);
if (chk1 || chk2) {
logMessage(Level.FINER, 2, "==>1.2 generateConclusions_definiteProvable: ==> add ambiguous (+D)", headLiteral);
Conclusion conclusion = new Conclusion(ConclusionType.DEFINITE_PROVABLE, headLiteral);
addRecord(conclusion);
addAmbiguousConclusion(conclusion, rule.getOriginalLabel());
} else {
boolean hasConflictRecord = false;
if (isRecordExist(conflictLiterals, ConclusionType.DEFINITE_PROVABLE)) hasConflictRecord = true;
if (isRecordExist(headLiteral, ConclusionType.DEFINITE_NOT_PROVABLE)) hasConflictRecord = true;
if (hasConflictRecord) {
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(rule.getOriginalLabel(), RuleType.STRICT,
ConclusionType.DEFINITE_NOT_PROVABLE, headLiteral, RuleInferenceStatus.DISCARDED);
newLiteralFind_definiteNotProvable(headLiteral, true);
} else {
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(rule.getOriginalLabel(), RuleType.STRICT,
ConclusionType.DEFINITE_PROVABLE, headLiteral, RuleInferenceStatus.APPICABLE);
newLiteralFind_definiteProvable(headLiteral, true);
}
}
}
break;
case DEFEASIBLE:
logMessage(Level.FINEST, 1, "==> ", literal, " (defeasible)");
// same as 'generateConclusions_defeasiblyProvable(Literal literal)'
// duplicated here for efficiency
if (containsUnprovedRuleInTheory(conflictLiterals, RuleType.DEFEASIBLE)) {
logMessage(Level.FINER, 2, "==>1.5 generateConclusions_definiteProvable: ==> add ambiguous (+d)", headLiteral);
Conclusion conclusion = new Conclusion(ConclusionType.DEFEASIBLY_PROVABLE, headLiteral);
addAmbiguousConclusion(conclusion, rule.getOriginalLabel());
addRecord(conclusion);
} else if (isRecordExist(headLiteral, ConclusionType.DEFEASIBLY_PROVABLE)) {
// do nothing
} else {
boolean chk1 = isAmbiguousConclusionExist(headLiteral, ConclusionType.DEFEASIBLY_NOT_PROVABLE);
boolean chk2 = isAmbiguousConclusionExist(conflictLiterals, ConclusionType.DEFEASIBLY_PROVABLE);
if (chk1 || chk2) {
logMessage(Level.FINER, 2, "==>1.6 generateConclusions_definiteProvable: ==> add ambiguous (+D)", headLiteral);
addAmbiguousConclusion(new Conclusion(ConclusionType.DEFEASIBLY_PROVABLE, headLiteral), rule.getOriginalLabel());
} else {
boolean hasConflictRecord = false;
if (isRecordExist(conflictLiterals, ConclusionType.DEFEASIBLY_PROVABLE)) hasConflictRecord = true;
if (isRecordExist(headLiteral, ConclusionType.DEFEASIBLY_NOT_PROVABLE)) hasConflictRecord = true;
if (hasConflictRecord) {
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(rule.getOriginalLabel(), RuleType.DEFEASIBLE,
ConclusionType.DEFEASIBLY_NOT_PROVABLE, headLiteral, RuleInferenceStatus.DISCARDED);
newLiteralFind_defeasiblyNotProvable(headLiteral, true);
} else {
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(rule.getOriginalLabel(), RuleType.DEFEASIBLE,
ConclusionType.DEFEASIBLY_PROVABLE, headLiteral, RuleInferenceStatus.APPICABLE);
newLiteralFind_defeasiblyProvable(headLiteral, true);
}
}
}
break;
default:
}
}
}
if (rulesToDelete.size() > 0) removeRules(rulesToDelete);
return ProcessStatus.SUCCESS;
}
protected ProcessStatus generateConclusions_definiteNotProvable(final Literal literal) throws ReasoningEngineException {
logMessage(Level.FINER, 0, "=== generate inference: definite not provable: ", literal);
Collection<Rule> rules = theory.getRules(literal).values();
Set<String> rulesToRemove = new TreeSet<String>();
List<Literal> inapplicableLiterals = new ArrayList<Literal>();
for (Rule rule : rules) {
if (rule.getRuleType() == RuleType.STRICT && rule.isBodyLiteral(literal)) {
rulesToRemove.add(rule.getLabel());
Literal headLiteral = rule.getHeadLiterals().get(0);
logMessage(Level.FINER, 1, "literals added=", headLiteral);
inapplicableLiterals.add(headLiteral);
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(rule.getOriginalLabel(), RuleType.STRICT,
ConclusionType.DEFINITE_NOT_PROVABLE, headLiteral, RuleInferenceStatus.DISCARDED);
}
}
if (rulesToRemove.size() > 0) removeRules(rulesToRemove);
// check whether the literal can be proved by other strict rules
// if not, add -D to the pending conclusion list
for (Literal inapplicableLiteral : inapplicableLiterals) {
logMessage(Level.FINEST, 1, "checking inapplicable literals for other rules=", inapplicableLiteral);
if (theory.containsInRuleHead(inapplicableLiteral, RuleType.STRICT)) {
// literal still provable by other strict rules, so do nothing
logMessage(Level.FINEST, 2, "literal [", inapplicableLiteral, "] is provable by other strict rules");
} else {
Set<Literal> conflictLiterals = getConflictLiterals(inapplicableLiteral);
boolean acChk1 = isAmbiguousConclusionExist(conflictLiterals, ConclusionType.DEFINITE_PROVABLE);
boolean acChk2 = isAmbiguousConclusionExist(inapplicableLiteral, ConclusionType.DEFINITE_NOT_PROVABLE);
boolean recChk1 = isRecordExist(conflictLiterals, ConclusionType.DEFINITE_PROVABLE);
boolean recChk2 = isRecordExist(inapplicableLiteral, ConclusionType.DEFINITE_PROVABLE);
if (acChk1 || acChk2 || !(recChk1 || recChk2)) {
// add to new conclusion list
newLiteralFind_definiteNotProvable(inapplicableLiteral, true);
}
}
}
return ProcessStatus.SUCCESS;
}
protected ProcessStatus generateConclusions_defeasiblyProvable(final Literal literal) throws ReasoningEngineException, TheoryException {
logMessage(Level.FINER, 0, "generate inference: defeasibly provable: ", literal);
Set<String> rulesToRemove = new TreeSet<String>();
Set<Rule> rulesModified = theory.removeBodyLiteralFromRules(literal, RuleType.DEFEASIBLE);
if (rulesModified.size() == 0) return ProcessStatus.SUCCESS;
for (Rule rule : rulesModified) {
logMessage(Level.FINER, 1, null, literal, ": rule=", rule, ", is empty body=" + rule.isEmptyBody());
if (rule.isEmptyBody()) {
Literal headLiteral = rule.getHeadLiterals().get(0);
rulesToRemove.add(rule.getLabel());
Set<Literal> conflictLiterals = getConflictLiterals(headLiteral);
boolean containsUnprovableRuleInTheory = containsUnprovedRuleInTheory(conflictLiterals, RuleType.DEFEASIBLE);
logMessage(Level.FINEST, 2, "==>2.0 conflictLiterals: ", conflictLiterals, ",unproved rules="
+ containsUnprovableRuleInTheory);
if (containsUnprovableRuleInTheory) {
logMessage(Level.FINER, 2, "==>2.1 generateConclusions_defeasiblyProvable: ==> add ambiguous (+d)", headLiteral);
Conclusion conclusion = new Conclusion(ConclusionType.DEFEASIBLY_PROVABLE, headLiteral);
addAmbiguousConclusion(conclusion, rule.getOriginalLabel());
addRecord(conclusion);
} else if (isRecordExist(headLiteral, ConclusionType.DEFEASIBLY_PROVABLE)) {
} else {
boolean chk1 = isAmbiguousConclusionExist(headLiteral, ConclusionType.DEFEASIBLY_NOT_PROVABLE);
boolean chk2 = isAmbiguousConclusionExist(conflictLiterals, ConclusionType.DEFEASIBLY_PROVABLE);
if (chk1 || chk2) {
logMessage(Level.FINER, 2, "==>2.2 generateConclusions_defeasiblyProvable: ==> add ambiguous (+D)", headLiteral);
addAmbiguousConclusion(new Conclusion(ConclusionType.DEFEASIBLY_PROVABLE, headLiteral), rule.getOriginalLabel());
} else {
boolean hasConflictRecord = false;
if (isRecordExist(conflictLiterals, ConclusionType.DEFEASIBLY_PROVABLE)) hasConflictRecord = true;
if (isRecordExist(headLiteral, ConclusionType.DEFEASIBLY_NOT_PROVABLE)) hasConflictRecord = true;
if (hasConflictRecord) {
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(rule.getOriginalLabel(), RuleType.DEFEASIBLE,
ConclusionType.DEFEASIBLY_NOT_PROVABLE, headLiteral, RuleInferenceStatus.DISCARDED);
newLiteralFind_defeasiblyNotProvable(headLiteral, true);
} else {
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(rule.getOriginalLabel(), RuleType.DEFEASIBLE,
ConclusionType.DEFEASIBLY_PROVABLE, headLiteral, RuleInferenceStatus.APPICABLE);
newLiteralFind_defeasiblyProvable(headLiteral, true);
}
}
}
}
}
logMessage(Level.FINER, 1, "generateConclusions_defeasiblyProvable.removeRules=", rulesToRemove);
if (rulesToRemove.size() > 0) removeRules(rulesToRemove);
return ProcessStatus.SUCCESS;
}
protected ProcessStatus generateConclusions_defeasiblyNotProvable(final Literal literal) throws ReasoningEngineException {
logMessage(Level.FINER, 0, "generate inference: defeasibly not provable: ", literal);
Collection<Rule> rules = theory.getRules(literal).values();
Set<String> rulesToRemove = new TreeSet<String>();
List<Literal> inapplicableLiterals = new ArrayList<Literal>();
if (rules == null) return ProcessStatus.SUCCESS;
for (Rule rule : rules) {
if (rule.getRuleType() == RuleType.DEFEASIBLE && rule.isBodyLiteral(literal)) {
rulesToRemove.add(rule.getLabel());
Literal headLiteral = rule.getHeadLiterals().get(0);
logMessage(Level.FINEST, 1, "literals added=", headLiteral);
inapplicableLiterals.add(headLiteral);
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(rule.getOriginalLabel(), RuleType.DEFEASIBLE,
ConclusionType.DEFEASIBLY_NOT_PROVABLE, headLiteral, RuleInferenceStatus.DISCARDED);
}
}
if (rulesToRemove.size() > 0) removeRules(rulesToRemove);
// check whether the literal can be proved by other strict rules
// if not, add -d to the pending conclusion list
for (Literal inapplicableLiteral : inapplicableLiterals) {
logMessage(Level.FINEST, 1, "checking inapplicable literals for other rules: ", inapplicableLiteral);
if (theory.containsInRuleHead(inapplicableLiteral, RuleType.DEFEASIBLE)) {
// literal still provable by other strict rules, so do nothing
logMessage(Level.FINEST, 2, "literal [", inapplicableLiteral, "] is provable by other defesible rules");
} else {
Set<Literal> conflictLiterals = getConflictLiterals(inapplicableLiteral);
boolean acChk1 = isAmbiguousConclusionExist(conflictLiterals, ConclusionType.DEFEASIBLY_PROVABLE);
boolean acChk2 = isAmbiguousConclusionExist(inapplicableLiteral, ConclusionType.DEFEASIBLY_NOT_PROVABLE);
boolean recChk1 = isRecordExist(conflictLiterals, ConclusionType.DEFEASIBLY_PROVABLE);
boolean recChk2 = isRecordExist(inapplicableLiteral, ConclusionType.DEFEASIBLY_PROVABLE);
if (acChk1 || acChk2 || !(recChk1 || recChk2)) {
newLiteralFind_defeasiblyNotProvable(inapplicableLiteral, true);
}
}
}
return ProcessStatus.SUCCESS;
}
@Override
protected ProcessStatus addPendingConclusion(Conclusion conclusion) {
if (isConclusionExist(conclusion)) return ProcessStatus.SUCCESS;
logMessage(Level.FINE, 3, "pending conclusion added: ", conclusion);
int ind = conclusion.getProvabilityLevel().ordinal();
pendingConclusions[ind].add(conclusion);
return ProcessStatus.SUCCESS;
}
protected ProcessStatus addAmbiguousConclusion(Conclusion conclusion, Set<String> ruleLabels) {
for (String ruleLabel : ruleLabels) {
addAmbiguousConclusion(conclusion, ruleLabel);
}
return ProcessStatus.SUCCESS;
}
protected ProcessStatus addAmbiguousConclusion(Conclusion conclusion, String ruleLabel) {
if (isConclusionExist(conclusion)) return ProcessStatus.SUCCESS;
logMessage(Level.FINE, 3, "ambiguous conclusion added: ", conclusion);
int ind = conclusion.getProvabilityLevel().ordinal();
Set<String> ruleSet = ambiguousConclusions[ind].get(conclusion);
if (null == ruleSet) {
ruleSet = new TreeSet<String>();
ambiguousConclusions[ind].put(conclusion, ruleSet);
}
ruleSet.add(ruleLabel);
addRecord(conclusion);
return ProcessStatus.SUCCESS;
}
protected ProcessStatus removeAmbiguousConclusion(Conclusion conclusion) {
if (isConclusionExist(conclusion)) return ProcessStatus.SUCCESS;
logMessage(Level.FINER, 3, "ambiguous conclusion to remove: ", conclusion);
int ind = conclusion.getProvabilityLevel().ordinal();
ambiguousConclusions[ind].remove(conclusion);
removeRecord(conclusion);
return ProcessStatus.SUCCESS;
}
protected void updateAmbiguousConclusions(int i) throws ReasoningEngineException {
System.out.println("-- -- SdlReasoningEngine.updateAmbiguousConclusions("+i+")");
if (ambiguousConclusions[i].size() == 0) return;
if (!AppConst.isDeploy) printEngineStatus("updateAmbiguousConclusions-before");
List<Conclusion> ambiguousConclusionToRemove = new ArrayList<Conclusion>();
List<Conclusion> recordsToRemove = new ArrayList<Conclusion>();
for (Entry<Conclusion, Set<String>> entry : ambiguousConclusions[i].entrySet()) {
Conclusion conclusion = entry.getKey();
Set<String> ruleLabels = entry.getValue();
Literal literal = conclusion.getLiteral();
Set<Literal> conflictLiterals = getConflictLiterals(literal);
boolean conflictLiteralInSccGroup = false;
for (Literal conflictLiteral : conflictLiterals) {
if (getSccGroup(conflictLiteral) != null) conflictLiteralInSccGroup = true;
}
Set<Rule> rulesWithLiteralAsHead = theory.getRulesWithHead(literal);
boolean keepLiteralInAmbiguousSet = false;
switch (conclusion.getConclusionType()) {
case DEFINITE_PROVABLE:
logMessage(Level.FINER, 1, "updateAmbiguousConclusion, check literal (definite): ", literal);
for (Rule r : rulesWithLiteralAsHead) {
if (!RuleType.STRICT.equals(r.getRuleType()))continue;
for (Literal bodyLiteral : r.getBodyLiterals()) {
if (bodyLiteral.isPlaceHolder()) keepLiteralInAmbiguousSet = true;
}
}
boolean chk1 = isRecordExist(conflictLiterals, ConclusionType.DEFINITE_PROVABLE);
if (keepLiteralInAmbiguousSet){
// defer the removal of literal until all rules generated
// by the superiority removal process have been evaluated
logMessage(Level.FINER, 2, "keep literal in ambiguous set temporary");
}else if (!containsUnprovedRuleInTheory(conflictLiterals, RuleType.STRICT)) {
ambiguousConclusionToRemove.add(conclusion);
if (chk1) {
recordsToRemove.add(conclusion);
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(ruleLabels, RuleType.STRICT,
ConclusionType.DEFINITE_NOT_PROVABLE, literal, RuleInferenceStatus.DEFEATED);
newLiteralFind_definiteNotProvable(literal, true);
} else {
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.APPICABLE);
newLiteralFind_definiteProvable(literal, true);
}
} else if (conflictLiteralInSccGroup && chk1) {
ambiguousConclusionToRemove.add(conclusion);
recordsToRemove.add(conclusion);
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.DISCARDED);
newLiteralFind_defeasiblyNotProvable(literal, true);
}
break;
case DEFEASIBLY_PROVABLE:
logMessage(Level.FINER, 1, "updateAmbiguousConclusion, check literal (defeasible): ", literal);
for (Rule r : rulesWithLiteralAsHead) {
if (!RuleType.DEFEASIBLE.equals(r.getRuleType()))continue;
for (Literal bodyLiteral : r.getBodyLiterals()) {
if (bodyLiteral.isPlaceHolder()) keepLiteralInAmbiguousSet = true;
}
}
boolean dchk4 = isRecordExist(conflictLiterals, ConclusionType.DEFEASIBLY_PROVABLE);
if (keepLiteralInAmbiguousSet) {
// defer the removal of literal until all rules generated
// by the superiority removal process have been evaluated
logMessage(Level.FINER, 2, "keep literal in ambiguous set temporary");
} else if (!containsUnprovedRuleInTheory(conflictLiterals, RuleType.DEFEASIBLE)) {
ambiguousConclusionToRemove.add(conclusion);
logMessage(Level.FINER, 0, "*** dchk4=", dchk4);
if (dchk4) {
recordsToRemove.add(conclusion);
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(ruleLabels, RuleType.DEFEASIBLE,
ConclusionType.DEFEASIBLY_NOT_PROVABLE, literal, RuleInferenceStatus.DEFEATED);
newLiteralFind_defeasiblyNotProvable(literal, true);
} else {
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.APPICABLE);
newLiteralFind_defeasiblyProvable(literal, true);
}
} else if (conflictLiteralInSccGroup && dchk4) {
ambiguousConclusionToRemove.add(conclusion);
recordsToRemove.add(conclusion);
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.DISCARDED);
newLiteralFind_defeasiblyNotProvable(literal, true);
}
break;
default:
}
}
logMessage(Level.FINER, 1, "ambiguousConclusionToRemove=", ambiguousConclusionToRemove);
for (Conclusion conclusion : ambiguousConclusionToRemove) {
ambiguousConclusions[i].remove(conclusion);
}
for (Conclusion record : recordsToRemove) {
removeRecord(record);
}
if (!AppConst.isDeploy) printEngineStatus("updateAmbiguousConclusions-after");
}
protected boolean hasPendingConclusions(int i) {
return pendingConclusions[i].size() > 0;
}
protected boolean hasAmbiguousConclusions(int i) {
return ambiguousConclusions[i].size() > 0;
}
/**
* return the next pending conclusion in the list and remove it from the
* pending conclusions list
* <p>
* this function will return all the definite (not) provable conclusions first and then the defeasible (not)
* provable conclusions
* </p>
*
* @return next pending conclusion in the list
* @throws ReasoningEngineException
*/
protected Conclusion getNextPendingConclusion() throws ReasoningEngineException {
// Conclusion pendingConclusion = null;
int totalPendingConclusionsCount = 0;
for (int i = 0; i < pendingConclusions.length; i++) {
// for (int i = 0; i < pendingConclusions.length && null == pendingConclusion; i++) {
totalPendingConclusionsCount += pendingConclusions[i].size();
if (totalPendingConclusionsCount == 0 && !hasAmbiguousConclusions(i)) {
if (i == 0 && theory.getStrictRulesCount() == 0) continue;
else if (i == 1 && theory.getDefeasibleRulesCount() == 0) continue;
}
if (!hasPendingConclusions(i) && hasAmbiguousConclusions(i)) {
// if (pendingConclusions[i].size() == 0 && ambiguousConclusions[i].size() > 0) {
// update ambiguous conclusions found
if (theoryWithLoops) getSccLiteralsGroupInTheory();
updateAmbiguousConclusions(i);
totalPendingConclusionsCount += pendingConclusions[i].size();
}
if (!hasPendingConclusions(i) && hasAmbiguousConclusions(i)) {
// if (pendingConclusions[i].size() == 0 && ambiguousConclusions[i].size() > 0) {
updateSccAmbiguousConclusions(i, Conf.isReasoningWithWellFoundedSemantics());
}
// well-found semantics
// - check for strongly connected literals if no new pending conclusions found after ambiguity check
if (Conf.isReasoningWithWellFoundedSemantics() //
&& i == pendingConclusions.length - 1 //
&& totalPendingConclusionsCount == 0 //
&& theory.getFactsAndAllRules().size() > 0) {
try {
if (updateStronglyConnectedComponents(true) > 0) {
int jj = 0;
while (jj < pendingConclusions.length && pendingConclusions[jj].size() == 0) {
jj++;
}
if (i > jj) i = jj;
if (!AppConst.isDeploy) logMessage(Level.FINEST, 2, "XXX, i=", i, ", jj=", jj);
}
} catch (ReasoningEngineException e) {
throw e;
} catch (Exception e) {
throw new ReasoningEngineException(getClass(), "Exception throw while generating strongly connected components", e);
}
}
if (pendingConclusions[i].size() > 0) {
// Conclusion nextConclusion=pendingConclusions[i].get(0);pendingConclusions[i].remove(0);return
// nextConclusion;
return pendingConclusions[i].removeFirst();
} else {
// some loop in the theory may occur
if ( hasAmbiguousConclusions(i)) {
logMessage(Level.FINER, 0, "*** ambiguousConclusions[", i, "].size()=" + ambiguousConclusions[i].size());
}
}
}
return null;
// return pendingConclusion;
}
// ======================================
// well-found semantics - start
//
protected boolean isBlockedBySccLiteral(Literal literal) {
Set<Rule> rules = theory.getRulesWithHead(literal);
Set<Rule> newRules = new TreeSet<Rule>();
Set<Rule> allRules = new TreeSet<Rule>();
int lastAllCheckedRulesCount = 0;
do {
lastAllCheckedRulesCount = allRules.size();
rules.addAll(newRules);
newRules.clear();
for (Rule rule : rules) {
for (Literal bodyLiteral : rule.getBodyLiterals()) {
Set<Literal> sccGroup = getSccGroup(bodyLiteral);
if (sccGroup != null) {
Set<String> rr = getRulesWithBodyLiteralOutOfSccGroup(bodyLiteral, sccGroup);
if (rr.size() == 0) return true;
}
newRules.addAll(theory.getRulesWithHead(bodyLiteral));
}
}
if (newRules.size() > 0) allRules.addAll(newRules);
} while (newRules.size() > 0 && lastAllCheckedRulesCount != allRules.size());
return false;
}
protected Set<Literal> getSccGroup(Literal literal) {
for (Set<Literal> sccGroup : sccLiteralsGroups) {
if (sccGroup.contains(literal)) return sccGroup;
}
return null;
}
protected void updateSccAmbiguousConclusions(int i, boolean isWellfounded) throws ReasoningEngineException {
List<Conclusion> unprovableConclusion = new ArrayList<Conclusion>();
List<Conclusion> ambiguousConclusionToRemove = new ArrayList<Conclusion>();
logMessage(Level.FINE, 0, "updateSccAmbiguousConclusions - start");
Set<String> rulesToRemove = new TreeSet<String>();
if (!isWellfounded) {
for (Set<Literal> sccLiteralsGroup : sccLiteralsGroups) {
for (Literal sccLiteral : sccLiteralsGroup) {
logMessage(Level.FINER, 1, "checking sccLiteral: ", sccLiteral);
boolean sccLiteralToRemove = false;
boolean conflictInSameSccGroup = isConflictLiteralInSameSccGroup(sccLiteral);
if (conflictInSameSccGroup) {
sccLiteralToRemove = true;
Set<Literal> conflictLiterals = getConflictLiterals(sccLiteral);
for (Literal conflictLiteral : conflictLiterals) {
if (isAmbiguousConclusionExist(conflictLiteral, ConclusionType.DEFEASIBLY_PROVABLE)) {
ambiguousConclusionToRemove.add(new Conclusion(ConclusionType.DEFEASIBLY_PROVABLE, conflictLiteral));
break;
}
}
} else {
Set<Literal> conflictLiterals = getConflictLiterals(sccLiteral);
for (Literal conflictLiteral : conflictLiterals) {
if (isAmbiguousConclusionExist(conflictLiteral, ConclusionType.DEFEASIBLY_PROVABLE)) {
sccLiteralToRemove = true;
break;
}
}
}
if (sccLiteralToRemove) {
for (Rule r : theory.getRules(sccLiteral).values()) {
// if (r.isHeadLiteral(sccLiteral)) {
// rulesToRemove.add(r.getLabel());
// }
ConclusionType t = (r.getRuleType() == RuleType.STRICT ? ConclusionType.DEFINITE_NOT_PROVABLE
: ConclusionType.DEFEASIBLY_NOT_PROVABLE);
Conclusion conclusion = new Conclusion(t, sccLiteral);
unprovableConclusion.add(conclusion);
// unprovableConclusion.add(new Conclusion(t, sccLiteral));
if (r.isHeadLiteral(sccLiteral)) {
rulesToRemove.add(r.getLabel());
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(r.getOriginalLabel(), conclusion,
RuleInferenceStatus.DISCARDED);
}
}
}
}
}
}
logMessage(Level.FINER, 1, "==> unprovableConclusion.size=" + unprovableConclusion.size());
if (unprovableConclusion.size() == 0) {
for (Conclusion conclusion : ambiguousConclusions[i].keySet()) {
Literal ambiguousLiteral = conclusion.getLiteral();
logMessage(Level.FINER, 1, "ambiguousLiteral=", ambiguousLiteral);
Set<Literal> conclictLiterals = getConflictLiterals(ambiguousLiteral);
logMessage(Level.FINEST, 1, "conclictLiterals=", conclictLiterals);
for (Literal conflictLiteral : conclictLiterals) {
if (isBlockedBySccLiteral(conflictLiteral)) {
boolean isConflictLiteralInSccGroup = (getSccGroup(conflictLiteral) != null);
logMessage(Level.FINEST, 2, "isBlockedBySccLiteral=true, isConflictLiteralInSccGroup=", isConflictLiteralInSccGroup);
Set<Rule> conflictHeadRules = theory.getRulesWithHead(conflictLiteral);
for (Rule conflictHeadRule : conflictHeadRules) {
boolean allBodyLiteralsAreAmbiguous = false;
boolean allrealLiterals = true;
ConclusionType conclusionType = (conflictHeadRule.getRuleType() == RuleType.STRICT ? ConclusionType.DEFINITE_PROVABLE
: ConclusionType.DEFEASIBLY_PROVABLE);
for (Literal bodyLiteral : conflictHeadRule.getBodyLiterals()) {
if (!isAmbiguousConclusionExist(bodyLiteral.getComplementClone(), conclusionType)) allBodyLiteralsAreAmbiguous = false;
else if (bodyLiteral.isPlaceHolder()) allrealLiterals = false;
}
logMessage(Level.FINEST, 3, "rule [", conflictHeadRule.getLabel(), "], allBodyLiteralsAreAmbiguous="
+ allBodyLiteralsAreAmbiguous + ", allrealLiterals=" + allrealLiterals);
if (allBodyLiteralsAreAmbiguous || allrealLiterals) {
// rulesToRemove.add(conflictHeadRule.getLabel());
ConclusionType t = (conflictHeadRule.getRuleType() == RuleType.STRICT ? ConclusionType.DEFINITE_NOT_PROVABLE
: ConclusionType.DEFEASIBLY_NOT_PROVABLE);
Conclusion tempConclusion = new Conclusion(t, conflictLiteral);
unprovableConclusion.add(tempConclusion);
// unprovableConclusion.add(new Conclusion(t, conflictLiteral));
rulesToRemove.add(conflictHeadRule.getLabel());
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(conflictHeadRule.getOriginalLabel(), tempConclusion,
RuleInferenceStatus.DISCARDED);
}
if (!isConflictLiteralInSccGroup && !isWellfounded) {
if (allrealLiterals) ambiguousConclusionToRemove.add(conclusion);
unresolveableConclusionsSet.add(new Conclusion(ConclusionType.DEFEASIBLY_NOT_PROVABLE, conclusion
.getLiteral()));
}
}
} else {
Set<Rule> conflictHeadRules = theory.getRulesWithHead(conflictLiteral);
for (Rule conflictHeadRule : conflictHeadRules) {
boolean allBodyLiteralsAreAmbiguous = true;
boolean allRealLiterals = true;
ConclusionType conclusionType = (conflictHeadRule.getRuleType() == RuleType.STRICT ? ConclusionType.DEFINITE_PROVABLE
: ConclusionType.DEFEASIBLY_PROVABLE);
for (Literal bodyLiteral : conflictHeadRule.getBodyLiterals()) {
if (!isAmbiguousConclusionExist(bodyLiteral.getComplementClone(), conclusionType))
allBodyLiteralsAreAmbiguous = false;
if (bodyLiteral.isPlaceHolder()) allRealLiterals = false;
}
logMessage(Level.FINEST, 3, "rule [", conflictHeadRule.getLabel(), "], allBodyLiteralsAreAmbiguous="
+ allBodyLiteralsAreAmbiguous + ", allRealLiterals=" + allRealLiterals);
if (allBodyLiteralsAreAmbiguous && !allRealLiterals) {
// rulesToRemove.add(conflictHeadRule.getLabel());
ConclusionType t = (conflictHeadRule.getRuleType() == RuleType.STRICT ? ConclusionType.DEFINITE_NOT_PROVABLE
: ConclusionType.DEFEASIBLY_NOT_PROVABLE);
Conclusion tempConclusion = new Conclusion(t, conflictLiteral);
unprovableConclusion.add(tempConclusion);
// unprovableConclusion.add(new Conclusion(t, conflictLiteral));
rulesToRemove.add(conflictHeadRule.getLabel());
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(conflictHeadRule.getOriginalLabel(), tempConclusion,
RuleInferenceStatus.DISCARDED);
}
}
}
}
}
}
if (!AppConst.isDeploy) {
logMessage(Level.INFO, 0, "rulesToRemove=" + rulesToRemove);
logMessage(Level.INFO, 0, "unprovableConclusion=" + unprovableConclusion);
logMessage(Level.INFO, 0, "ambiguousConclusionToRemove=" + ambiguousConclusionToRemove);
logMessage(Level.INFO, 0, "unresolveableConclusionsSet=" + unresolveableConclusionsSet);
}
for (Conclusion c : ambiguousConclusionToRemove) {
removeAmbiguousConclusion(c);
}
removeRules(rulesToRemove);
for (Conclusion c : unprovableConclusion) {
if (ConclusionType.DEFINITE_NOT_PROVABLE == c.getConclusionType()) {
newLiteralFind_definiteNotProvable(c.getLiteral(), true);
} else {
newLiteralFind_defeasiblyNotProvable(c.getLiteral(), true);
}
}
updateAmbiguousConclusions(i);
if (!AppConst.isDeploy) printEngineStatus("updateSccAmbiguousConclusions");
logMessage(Level.FINE, 0, "updateSccAmbiguousConclusions - end");
}
protected boolean isConflictLiteralInSameSccGroup(Literal literal) {
Set<Literal> sccGroup = getSccGroup(literal);
if (null == sccGroup) return false;
boolean inSameSccGroup = sccGroup.contains(literal.getComplementClone());
return inSameSccGroup;
}
protected boolean isSelfLoop(Literal literal) {
Map<String, Rule> rules = theory.getRules(literal);
for (Rule rule : rules.values()) {
if (rule.isBodyLiteral(literal) && rule.isHeadLiteral(literal)) return true;
}
return false;
}
protected void getSccLiteralsGroupInTheory() throws ReasoningEngineException {
TheoryAnalyser theoryAnalyser;
try {
theoryAnalyser = getTheoryAnalyser();
sccLiteralsGroups = theoryAnalyser.getStronglyConnectedLiterals();
// remove redundant group
for (int i = sccLiteralsGroups.size() - 1; i >= 0; i--) {
Set<Literal> scc = sccLiteralsGroups.get(i);
if (scc.size() == 1 && !isSelfLoop(scc.iterator().next())) {
logMessage(Level.FINER, 0, "*** scc (removed) =", scc);
sccLiteralsGroups.remove(i);
} else {
logMessage(Level.FINER, 0, "*** scc literal group=", scc);
}
}
if (sccLiteralsGroups.size() == 0) {
theoryWithLoops = false;
}
} catch (ReasoningEngineException e) {
throw e;
} catch (Exception e) {
throw new ReasoningEngineException(getClass(), e);
}
}
protected Set<String> getRulesWithBodyLiteralOutOfSccGroup(Literal literal, Set<Literal> sccGroup) {
Set<Rule> rules = theory.getRulesWithHead(literal);
Set<String> nonSccLiteralRules = new TreeSet<String>();
for (Rule rule : rules) {
if (rule.getBodyLiterals().size() > 0) {
boolean containsSccLiteralInBody = false;
for (Literal bodyLiteral : rule.getBodyLiterals()) {
if (sccGroup.contains(bodyLiteral)) containsSccLiteralInBody = true;
}
if (!containsSccLiteralInBody) nonSccLiteralRules.add(rule.getLabel());
}
}
return nonSccLiteralRules;
}
protected int updateStronglyConnectedComponents(boolean updateSccLiteralsGroup) throws ReasoningEngineException {
logMessage(Level.FINER, 1, "updateStronglyConnectedComponents - start");
int literalCount = 0;
Set<String> rulesToRemove = new TreeSet<String>();
try {
if (updateSccLiteralsGroup) getSccLiteralsGroupInTheory();
if (null == sccLiteralsGroups || sccLiteralsGroups.size() == 0) return literalCount;
for (Set<Literal> literalsGroup : sccLiteralsGroups) {
logMessage(Level.FINEST, 2, "** literalsGroup - [", literalsGroup.size(), "]-", literalsGroup);
if (literalsGroup.size() == 1) {
Literal literal = literalsGroup.iterator().next();
if (isSelfLoop(literal)) {
// check to see if there are any applicable rules with
// body literal out of SCC group
Set<String> applicableRules = getRulesWithBodyLiteralOutOfSccGroup(literal, literalsGroup);
if (applicableRules.size() > 0) {
Set<Rule> rules = theory.getRulesWithHead(literal);
for (Rule r : rules) {
if (!applicableRules.contains(r.getLabel())) rulesToRemove.add(r.getLabel());
}
} else {
logMessage(Level.FINEST, 3, "self looping literal added to conclusion set [", literal, "]");
updateStronglyConnectedComponents_addConclusions(literal);
literalCount++;
}
} else {
// literal is not self looping
}
} else {
for (Literal literal : literalsGroup) {
// check to see if there are any applicable rules with
// body literal out of SCC group
Set<String> applicableRules = getRulesWithBodyLiteralOutOfSccGroup(literal, literalsGroup);
if (applicableRules.size() > 0) {
Set<Rule> rules = theory.getRulesWithHead(literal);
for (Rule r : rules) {
if (!applicableRules.contains(r.getLabel())) rulesToRemove.add(r.getLabel());
}
} else {
updateStronglyConnectedComponents_addConclusions(literal);
literalCount++;
}
}
}
}
if (rulesToRemove.size() > 0) removeRules(rulesToRemove);
return literalCount;
} catch (ReasoningEngineException e) {
throw e;
} catch (Exception e) {
logMessage(Level.SEVERE, 2, "*** " + TextUtilities.getExceptionMessage(e));
throw new ReasoningEngineException(getClass(), e);
} finally {
logMessage(Level.FINER, 1, "updateStronglyConnectedComponents - end");
}
}
protected void updateStronglyConnectedComponents_addConclusions(Literal literal) {
Set<Rule> rules = theory.getRulesWithHead(literal);
for (Rule rule : rules) {
switch (rule.getRuleType()) {
case STRICT:
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(rule.getOriginalLabel(), RuleType.STRICT,
ConclusionType.DEFINITE_NOT_PROVABLE, literal, RuleInferenceStatus.DISCARDED);
newLiteralFind_definiteNotProvable(literal, true);
break;
case DEFEASIBLE:
if (isLogInferenceProcess)
getInferenceLogger().updateRuleInferenceStatus(rule.getOriginalLabel(), RuleType.DEFEASIBLE,
ConclusionType.DEFEASIBLY_NOT_PROVABLE, literal, RuleInferenceStatus.DISCARDED);
newLiteralFind_defeasiblyNotProvable(literal, true);
break;
default:
}
}
}
//
// well-found semantics - end
// ======================================
protected ProcessStatus addConclusion(Conclusion conclusion) throws ReasoningEngineException {
logMessage(Level.FINE, 1, "conclusion added: ", conclusion);
Literal literal = conclusion.getLiteral();
Map<ConclusionType, Conclusion> conclusionList = conclusions.get(literal);
if (null == conclusionList) {
conclusionList = new TreeMap<ConclusionType, Conclusion>();
conclusions.put(literal, conclusionList);
}
conclusionList.put(conclusion.getConclusionType(), conclusion);
return ProcessStatus.SUCCESS;
}
protected boolean isConclusionExist(Conclusion conclusion) {
return isConclusionExist(conclusion.getLiteral(),conclusion.getConclusionType());
// if (conclusion == null) return false;
//
// Map<ConclusionType, Conclusion> conclusionList = conclusions.get(conclusion.getLiteral());
// if (null == conclusionList) return false;
// if (conclusionList.containsKey(conclusion.getConclusionType())) return true;
// return false;
}
protected boolean isConclusionExist(Literal literal,ConclusionType conclusionType) {
if (null==literal)return false;
Map<ConclusionType,Conclusion> conclusionList=conclusions.get(literal);
if (null==conclusionList)return false;
return conclusionList.containsKey(conclusionType);
// if (conclusionList.containsKey(conclusionType)) return true;
// return false;
}
protected boolean isAmbiguousConclusionExist(Literal literal, ConclusionType conclusionType) {
Conclusion conclusion = new Conclusion(conclusionType, literal);
int ind = conclusionType.getProvabilityLevel().ordinal();
boolean isExist = ambiguousConclusions[ind].containsKey(conclusion);
// int i = 0;
// switch (conclusionType) {
// case DEFINITE_PROVABLE:
// case DEFINITE_NOT_PROVABLE:
// i = 0;
// break;
// case DEFEASIBLY_PROVABLE:
// case DEFEASIBLY_NOT_PROVABLE:
// i = 1;
// break;
// default:
// }
// boolean isExist = ambiguousConclusions[i].containsKey(conclusion);
logMessage(Level.FINEST, 3, "isAmbiguousConclusionExist", literal, conclusionType, "=", isExist);
return isExist;
}
protected boolean isAmbiguousConclusionExist(Collection<Literal> literals, ConclusionType conclusionType) {
for (Literal literal : literals) {
if (isAmbiguousConclusionExist(literal, conclusionType)) return true;
}
return false;
}
protected boolean isTempConclusionExist(Collection<Literal> literalsList, TreeSet<Literal> tempConclusionSet) {
// protected boolean isTempConclusionExist(Collection<Literal> literalsList, TreeSet<Literal> tempConclusionSet,
// ConclusionType conclusionType) {
for (Literal literal : literalsList) {
// Conclusion c = new Conclusion(conclusionType, literal);
// if (tempConclusionSet.contains(c)) return true;
if (tempConclusionSet.contains(literal)) return true;
}
return false;
}
protected void printEngineStatus(final String callerName) {
String className = getClass().getName();
String msg = getReasoningEngineUtilities().generateEngineInferenceStatusMessage(className + "." + callerName,//
theory, conclusions, //
pendingConclusions, //
ambiguousConclusions, null, getRecords());
logMessage(Level.INFO, 0, msg);
}
protected void printPendingConclusionSet(Set<Literal> unprovedStrictRuleLiterals, Set<Literal> unprovedDefeasibleRuleLiterals,//
Set<Conclusion> tempPosDefiniteConclusionSet,Set<Conclusion> tempPosDefeasbileConclusionSet) {
StringBuilder sb = new StringBuilder();
sb.append("---\n--- printPendingConclusionSet - start\n---");
sb.append("\n--tempPosDefiniteConclusionSet");
for (Conclusion conclusion : tempPosDefiniteConclusionSet) {
sb.append("\n ").append(conclusion);
}
sb.append("\n--tempPosDefeasbileConclusionSet");
for (Conclusion conclusion : tempPosDefeasbileConclusionSet) {
sb.append("\n ").append(conclusion);
}
if (unprovedStrictRuleLiterals.size() > 0) {
sb.append("\n--unprovedStrictRuleLiterals");
for (Literal literal : unprovedStrictRuleLiterals) {
sb.append("\n ").append(literal);
}
}
if (unprovedDefeasibleRuleLiterals.size() > 0) {
sb.append("\n--unprovedDefeasibleRuleLiterals");
for (Literal literal : unprovedDefeasibleRuleLiterals) {
sb.append("\n ").append(literal);
}
}
sb.append("\n---\n--- printPendingConclusionSet - end\n---");
logMessage(Level.INFO, 0, sb.toString());
}
@Override
protected String getProgressMessage() {
int pendingConclusionsCount = pendingConclusions[0].size() + pendingConclusions[1].size();
pendingConclusionsCount += (ambiguousConclusions[0].size() + ambiguousConclusions[1].size());
long rulesCount = theory.getStrictRulesCount() + theory.getDefeasibleRulesCount();
return (pendingConclusionsCount + " literal(s) pending to process, " + rulesCount + " rules remain in theory.");
}
}