/** * 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.mdl; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import java.util.logging.Level; import spindle.core.dom.Conclusion; import spindle.core.dom.ConclusionType; import spindle.core.dom.Literal; import spindle.core.dom.Mode; import spindle.core.dom.Rule; import spindle.core.dom.RuleType; import spindle.engine.ReasoningEngineException; import spindle.engine.sdl.SdlReasoningEngine; import spindle.sys.AppConst; import spindle.tools.explanation.RuleInferenceStatus; /** * MDL Reasoning Engine. * * @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory * @since version 1.0.0 * @version Last modified 2012.08.20 */ public class MdlReasoningEngine extends SdlReasoningEngine { protected Map<String, Set<String>> strongerModeSet = null; public MdlReasoningEngine() { super(); } @Override protected void initialize() throws ReasoningEngineException { strongerModeSet = theory.getStrongModeSet(); super.initialize(); } protected Set<Literal> getConflictLiteralListWithoutOperatorChange(final Literal literal) { Set<Literal> conflictLiteralList = new TreeSet<Literal>(); conflictLiteralList.add(literal.getComplementClone()); Mode literalMode = literal.getMode(); if (!"".equals(literalMode.getName())) { Literal conflictLiteral = literal.clone(); conflictLiteral.setMode(literalMode.getComplementClone()); conflictLiteralList.add(conflictLiteral); } return conflictLiteralList; } // remove ambiguity caused by complementary literal protected void removeComplementLiteralAmbiguity(int i) { logMessage(Level.FINE, 1, "=== removeComplementLiteralAmbiguity - start ==="); 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 = getConflictLiteralListWithoutOperatorChange(literal); switch (conclusion.getConclusionType()) { case DEFINITE_PROVABLE: logMessage(Level.FINER, 2, "removeComplementLiteralAmbiguity, check literal (definite): ", literal); if (!containsUnprovedRuleInTheory(conflictLiterals, RuleType.STRICT)) { if (isAmbiguousConclusionExist(conflictLiterals, ConclusionType.DEFINITE_PROVABLE)) { ambiguousConclusionToRemove.add(conclusion); recordsToRemove.add(new Conclusion(ConclusionType.DEFINITE_PROVABLE, literal)); if (isLogInferenceProcess) getInferenceLogger().updateRuleInferenceStatus(ruleLabels, RuleType.STRICT, ConclusionType.DEFINITE_NOT_PROVABLE, literal, RuleInferenceStatus.DEFEATED); newLiteralFind_definiteNotProvable(literal, true); } } break; case DEFEASIBLY_PROVABLE: logMessage(Level.FINER, 2, "removeComplementLiteralAmbiguity, check literal (defeasible): ", literal); if (!containsUnprovedRuleInTheory(conflictLiterals, RuleType.DEFEASIBLE)) { if (isAmbiguousConclusionExist(conflictLiterals, ConclusionType.DEFEASIBLY_PROVABLE)) { ambiguousConclusionToRemove.add(conclusion); recordsToRemove.add(new Conclusion(ConclusionType.DEFEASIBLY_PROVABLE, literal)); if (isLogInferenceProcess) getInferenceLogger().updateRuleInferenceStatus(ruleLabels, RuleType.DEFEASIBLE, ConclusionType.DEFEASIBLY_NOT_PROVABLE, literal, RuleInferenceStatus.DEFEATED); newLiteralFind_defeasiblyNotProvable(literal, true); } } break; default: } } for (Conclusion conclusion : ambiguousConclusionToRemove) { ambiguousConclusions[i].remove(conclusion); } for (Conclusion record : recordsToRemove) { removeRecord(record); } logMessage(Level.FINE, 1, "=== removeComplementLiteralAmbiguity - end ==="); } @Override protected void updateAmbiguousConclusions(int i) { if (ambiguousConclusions[i].size() == 0) return; logMessage(Level.FINE, 0, "MdlReasoningEngine.updateAmbiguousConclusions - start, i=", i); if (!AppConst.isDeploy) printEngineStatus("updateAmbiguousConclusions-before"); List<Conclusion> ambiguousConclusionToRemove = new ArrayList<Conclusion>(); List<Conclusion> recordsToRemove = new ArrayList<Conclusion>(); // remove ambiguity caused by complementary literals removeComplementLiteralAmbiguity(i); // remove ambiguity based on modal operator strength 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 (null!=getSccGroup(conflictLiteral))conflictLiteralInSccGroup=true; } switch (conclusion.getConclusionType()) { case DEFINITE_PROVABLE: logMessage(Level.FINER, 1, "updateAmbiguousConclusion [MDL], check literal (definite): ", literal); if (!containsUnprovedRuleInTheory(conflictLiterals, RuleType.STRICT)) { boolean chk2 = isRecordExist(conflictLiterals, ConclusionType.DEFINITE_PROVABLE); if (chk2) { ambiguousConclusionToRemove.add(conclusion); int conflictLiteralExistCount = 0; int strongModeCount = 0; for (Literal conflictLiteral : conflictLiterals) { if (isRecordExist(conflictLiteral, ConclusionType.DEFINITE_PROVABLE)) { conflictLiteralExistCount++; if (hasStrongerMode(literal, conflictLiteral)) { logMessage(Level.FINEST, 2, null, literal, " hasStrongerMode: ", conflictLiteral); strongModeCount++; } } } // only conclusion with strongest modal operator is concluded if (strongModeCount == conflictLiteralExistCount) { // addPendingConclusion(new Conclusion(ConclusionType.DEFINITE_PROVABLE, literal)); // ambiguousConclusionToRemove.add(conclusion); if (isLogInferenceProcess) getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.APPICABLE); newLiteralFind_definiteProvable(literal,true); } else { // recordsToRemove.add(new Conclusion(ConclusionType.DEFINITE_PROVABLE, literal)); recordsToRemove.add(conclusion); // addPendingConclusion(new Conclusion(ConclusionType.DEFINITE_NOT_PROVABLE, literal)); // ambiguousConclusionToRemove.add(conclusion); if (isLogInferenceProcess) getInferenceLogger().updateRuleInferenceStatus(ruleLabels, RuleType.STRICT, ConclusionType.DEFINITE_NOT_PROVABLE, literal, RuleInferenceStatus.DEFEATED); newLiteralFind_definiteNotProvable(literal,true); } } else { // addPendingConclusion(new Conclusion(ConclusionType.DEFINITE_PROVABLE, literal)); ambiguousConclusionToRemove.add(conclusion); if (isLogInferenceProcess) getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.APPICABLE); newLiteralFind_definiteProvable(literal,true); } } break; case DEFEASIBLY_PROVABLE: logMessage(Level.FINER, 1, "updateAmbiguousConclusion [MDL], check literal (defeasible): ", literal); Set<Rule>rulesWithLiteralAsHead=theory.getRulesWithHead(literal); boolean keepLiteralInAmbiguousSet=false; for (Rule r:rulesWithLiteralAsHead){ for (Literal bodyLiteral:r.getBodyLiterals()){ if (bodyLiteral.isPlaceHolder())keepLiteralInAmbiguousSet=true; } } boolean dchk2 = 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); if (dchk2) { int conflictLiteralExistCount = 0; int strongModeCount = 0; for (Literal conflictLiteral : conflictLiterals) { if (isRecordExist(conflictLiteral, ConclusionType.DEFEASIBLY_PROVABLE)) { conflictLiteralExistCount++; if (hasStrongerMode(literal, conflictLiteral)) { logMessage(Level.FINEST, 2, null, literal, " hasStrongerMode: ", conflictLiteral); strongModeCount++; } } } // only conclusion with strongest modal operator is concluded if (strongModeCount == conflictLiteralExistCount) { // addPendingConclusion(new Conclusion(ConclusionType.DEFEASIBLY_PROVABLE, literal)); // ambiguousConclusionToRemove.add(conclusion); if (isLogInferenceProcess) getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.APPICABLE); newLiteralFind_defeasiblyProvable(literal,true); } else { recordsToRemove.add(new Conclusion(ConclusionType.DEFEASIBLY_PROVABLE, literal)); // ambiguousConclusionToRemove.add(conclusion); // Conclusion negConclusion = new Conclusion(ConclusionType.DEFEASIBLY_NOT_PROVABLE, literal); // addPendingConclusion(negConclusion); if (isLogInferenceProcess) getInferenceLogger().updateRuleInferenceStatus(ruleLabels,RuleType.DEFEASIBLE, ConclusionType.DEFEASIBLY_NOT_PROVABLE,literal, RuleInferenceStatus.DEFEATED); newLiteralFind_defeasiblyNotProvable(literal,true); } } else { // addPendingConclusion(new Conclusion(ConclusionType.DEFEASIBLY_PROVABLE, literal)); // ambiguousConclusionToRemove.add(conclusion); if (isLogInferenceProcess) getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.APPICABLE); newLiteralFind_defeasiblyProvable(literal,true); } } else if (conflictLiteralInSccGroup && dchk2){ ambiguousConclusionToRemove.add(conclusion); recordsToRemove.add(conclusion); if (isLogInferenceProcess) getInferenceLogger().updateRuleInferenceStatus(ruleLabels, conclusion, RuleInferenceStatus.DISCARDED); newLiteralFind_defeasiblyNotProvable(literal,true); } break; default: } } for (Conclusion conclusion : ambiguousConclusionToRemove) { ambiguousConclusions[i].remove(conclusion); } for (Conclusion record : recordsToRemove) { removeRecord(record); } if (!AppConst.isDeploy) printEngineStatus("updateAmbiguousConclusions-after"); logMessage(Level.FINE, 0, "MdlReasoningEngine.updateAmbiguousConclusions - end, i=", i); } private boolean hasStrongerMode(Literal literal, Literal conflictLiteral) { Mode m1 = literal.getMode(); Mode m2 = conflictLiteral.getMode(); if (m1.equals(m2)) return false; if (m1.getName().equals(m2.getName()) && m1.isNegation() != m2.isNegation()) return false; if (!strongerModeSet.containsKey(m1.getName())) return false; Set<String> modeList = strongerModeSet.get(m1.getName()); String m2ModeName = m2.getName(); for (String s : modeList) { if (s.equals(m2ModeName)) { return true; } } return false; } }