/** * 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; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.logging.Level; import com.app.utils.Utilities.ProcessStatus; import spindle.core.MessageType; import spindle.core.dom.DomUtilities; import spindle.core.dom.Literal; import spindle.core.dom.Mode; import spindle.core.dom.Rule; import spindle.core.dom.RuleException; import spindle.core.dom.RuleType; import spindle.core.dom.Superiority; import spindle.core.dom.Theory; import spindle.core.dom.TheoryException; import spindle.sys.AppModuleBase; import spindle.sys.AppModuleListener; import spindle.sys.Messages; import spindle.sys.message.ErrorMessage; import spindle.sys.message.SystemMessage; /** * Base class for Theory normalizer. * * @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory * @since version 1.1.0 */ public abstract class TheoryNormalizer extends AppModuleBase { private static final String DEFEASIBLE_RULE_POSTFIX_A = ".a"; private static final String DEFEASIBLE_RULE_POSTFIX_C = ".c"; private static final String DEFEATER_POSTFIX_A = ".a"; private static final String DEFEATER_POSTFIX_C = ".c"; private static final String SUPERIORITY_RULE_PREFIX = "s."; private static final String SUPERIORITY_RULE_POSTFIX_PLUS = "+"; private static final String SUPERIORITY_RULE_POSTFIX_MINUS = "-"; private static final String SYMBOL_INF = "inf"; protected static final String TRANSFORM_POSTFIX = "'"; protected static final String TRANSFORM_POSTFIX2 = "*"; protected static final String FACT_RULE_TRANSFORM_PREFIX = "fact."; protected Theory theory = null; protected Map<String, Rule> factsAndRules = null; public TheoryNormalizer() { theory = null; factsAndRules = null; } public Theory getTheory() { return theory; } public void setTheory(final Theory theory) { this.theory = theory; factsAndRules = this.theory.getFactsAndAllRules(); } /** * transform theory to regular form and convert all modal operators in all rules and literals for MDL theory * * @return ProcessStatus.SUCCESS if completed successfully * @throws TheoryNormalizerException */ public ProcessStatus transformTheoryToRegularForm() throws TheoryNormalizerException { if (factsAndRules == null) throw new TheoryNormalizerException(getClass(), ErrorMessage.THEORY_NULL_THEORY); logMessage(Level.FINE, 0, Messages.getSystemMessage(SystemMessage.THEORY_NORMALIZER_REGULAR_FORM_TRANSFORMATION)); transformTheoryToRegularFormImpl(); return ProcessStatus.SUCCESS; } public ProcessStatus removeDefeater() throws TheoryNormalizerException { if (theory == null) throw new TheoryNormalizerException(getClass(), ErrorMessage.THEORY_NULL_THEORY); removeDefeaterImpl(); return ProcessStatus.SUCCESS; } public ProcessStatus removeSuperiority() throws TheoryNormalizerException { if (theory == null) throw new TheoryNormalizerException(getClass(), ErrorMessage.THEORY_NULL_THEORY); removeSuperiorityImpl(); return ProcessStatus.SUCCESS; } /** * add literals to the body of a rule * * <pre> * assumed that the literal is a place holder (dummy literal) if postfix is defined * </pre> * * @param rule * @param literals * @param postfix * @throws RuleException */ protected void addBodyLiterals(Rule rule, List<Literal> literals, String postfix) throws RuleException { try { if (literals == null || literals.size() == 0) { } else { if ("".equals(postfix)) { for (Literal literal : literals) { rule.addBodyLiteral(literal); } } else { for (Literal literal : literals) { Literal newLiteral = DomUtilities.getLiteral( // literal.getName() + postfix, literal.isNegation(), // literal.getMode(), // literal.getTemporal(), // literal.getPredicates(), // true); rule.addBodyLiteral(newLiteral); } } } } catch (Exception e) { throw new RuleException(e); } } /** * add literals to the head of a rule * * <pre> * assumed that the literal is a place holder (dummy literal) if postfix is defined * </pre> * * @param rule * @param literals * @param postfix * @throws RuleException */ protected void addHeadLiterals(Rule rule, List<Literal> literals, String postfix) throws RuleException { try { if (literals == null || literals.size() == 0) return; if ("".equals(postfix)) { for (Literal literal : literals) { rule.addHeadLiteral(literal); } } else { for (Literal literal : literals) { Literal newLiteral = DomUtilities.getLiteral( // literal.getName() + postfix, literal.isNegation(), // literal.getMode(),// literal.getTemporal(), // literal.getPredicates(),// true); rule.addHeadLiteral(newLiteral); } } } catch (RuleException e) { throw e; } catch (Exception e) { throw new RuleException(e); } } // ======================== // implementation // private void removeSuperiorityImpl() throws TheoryNormalizerException { List<Superiority> superiority = theory.getAllSuperiority(); List<Rule> rulesToAdd = new ArrayList<Rule>(); Set<String> rulesToDelete = new TreeSet<String>(); removeSuperiority_ruleModification(rulesToAdd, rulesToDelete); // superiority transform Rule newRule1 = null; Rule newRule2 = null; try { for (Superiority s : superiority) { newRule1 = null; newRule2 = null; String superiorRuleId = s.getSuperior(); String inferiorRuleId = s.getInferior(); Rule superiorRule = factsAndRules.get(superiorRuleId); Rule inferiorRule = factsAndRules.get(inferiorRuleId); if (null == superiorRule) throw new TheoryNormalizerException(getClass(), ErrorMessage.THEORY_SUPERIOR_RULE_NOT_FOUND_IN_THEORY, new Object[] { superiorRuleId }); if (null == inferiorRule) throw new TheoryNormalizerException(getClass(), ErrorMessage.THEORY_INFERIOR_RULE_NOT_FOUND_IN_THEORY, new Object[] { inferiorRuleId }); Mode superiorRuleMode = superiorRule.getMode(); Mode inferiorRuleMode = inferiorRule.getMode(); Literal supRuleHead = superiorRule.getHeadLiterals().get(0); Literal infRuleHead = inferiorRule.getHeadLiterals().get(0); if (supRuleHead.isComplementTo(infRuleHead)) { String newSupRuleLabel = theory.getUniqueRuleLabel(SUPERIORITY_RULE_PREFIX); Literal bodyLiteral = DomUtilities.getLiteral(SYMBOL_INF + "(" + superiorRuleId + ")+", true, // superiorRuleMode,null, null, true); Literal headLiteralPlus = DomUtilities.getLiteral(SYMBOL_INF + "(" + inferiorRuleId + ")+", false,// inferiorRuleMode,null, null, true); Literal headLiteralMinus = DomUtilities.getLiteral(SYMBOL_INF + "(" + inferiorRuleId + ")-", false, // inferiorRuleMode,null, null, true); newRule1 = DomUtilities.getRule(newSupRuleLabel + SUPERIORITY_RULE_POSTFIX_PLUS, RuleType.DEFEASIBLE); newRule1.setOriginalLabel(superiorRuleId); newRule1.setMode(superiorRuleMode); newRule1.addBodyLiteral(bodyLiteral); newRule1.addHeadLiteral(headLiteralPlus); newRule2 = DomUtilities.getRule(newSupRuleLabel + SUPERIORITY_RULE_POSTFIX_MINUS, RuleType.DEFEASIBLE); newRule2.setOriginalLabel(inferiorRuleId); newRule2.setMode(superiorRuleMode); newRule2.addBodyLiteral(bodyLiteral); newRule2.addHeadLiteral(headLiteralMinus); rulesToAdd.add(newRule1); rulesToAdd.add(newRule2); } else { fireTheoryNormalizerMessage(MessageType.WARNING, "The heads of [" + superiorRuleId + "] and [" + inferiorRuleId + "] are not complement to each other! Superiority relation ignored!"); } } theory.updateTheory(rulesToAdd, rulesToDelete, null); theory.clearSuperiority(); } catch (TheoryException e) { throw new TheoryNormalizerException(getClass(), ErrorMessage.TRANSFORMATION_SUPERIORITY_REMOVAL_ERROR, "Exception throw while updating theory", e); } catch (Exception e) { throw new TheoryNormalizerException(getClass(), ErrorMessage.TRANSFORMATION_SUPERIORITY_REMOVAL_ERROR, "Exception throw whlie removing superiority", e); } } private ProcessStatus removeSuperiority_ruleModification(final List<Rule> rulesToAdd, // Set<String> rulesToDelete) throws TheoryNormalizerException { Rule newRule1 = null; Rule newRule2 = null; try { for (Rule rule : factsAndRules.values()) { newRule1 = null; newRule2 = null; String ruleLabel = rule.getLabel(); String originalRuleLabel=rule.getOriginalLabel(); Mode ruleMode = rule.getMode(); switch (rule.getRuleType()) { case DEFEASIBLE: Literal literalDef = DomUtilities.getLiteral("inf(" + ruleLabel + ")+", true, // ruleMode, null,null, true); newRule1 = DomUtilities.getRule(ruleLabel + DEFEASIBLE_RULE_POSTFIX_A, RuleType.DEFEASIBLE); newRule1.setOriginalLabel(originalRuleLabel); newRule1.setMode(ruleMode); addBodyLiterals(newRule1, rule.getBodyLiterals(), ""); newRule1.addHeadLiteral(literalDef); newRule2 = DomUtilities.getRule(ruleLabel + DEFEASIBLE_RULE_POSTFIX_C, RuleType.DEFEASIBLE); newRule2.setOriginalLabel(originalRuleLabel); newRule2.setMode(ruleMode); newRule2.addBodyLiteral(literalDef); addHeadLiterals(newRule2, rule.getHeadLiterals(), ""); rulesToAdd.add(newRule1); rulesToAdd.add(newRule2); rulesToDelete.add(ruleLabel); break; case DEFEATER: Literal literalDft = DomUtilities.getLiteral("inf(" + ruleLabel + ")-", true, // ruleMode,null, null, true); newRule1 = DomUtilities.getRule(ruleLabel + DEFEATER_POSTFIX_A, RuleType.DEFEASIBLE); newRule1.setOriginalLabel(originalRuleLabel); newRule1.setMode(ruleMode); addBodyLiterals(newRule1, rule.getBodyLiterals(), ""); newRule1.addHeadLiteral(literalDft); newRule2 = DomUtilities.getRule(ruleLabel + DEFEATER_POSTFIX_C, RuleType.DEFEATER); newRule2.setOriginalLabel(originalRuleLabel); newRule2.setMode(ruleMode); newRule2.addBodyLiteral(literalDft); addHeadLiterals(newRule2, rule.getHeadLiterals(), ""); rulesToAdd.add(newRule1); rulesToAdd.add(newRule2); rulesToDelete.add(ruleLabel); break; default: } } } catch (Exception e) { throw new TheoryNormalizerException(getClass(), ErrorMessage.TRANSFORMATION_DEFEATER_REMOVAL_ERROR, e); } return ProcessStatus.SUCCESS; } private void removeDefeaterImpl() throws TheoryNormalizerException { List<Rule> rulesToAdd = new ArrayList<Rule>(); Set<String> rulesToDelete = new TreeSet<String>(); Map<String, List<Rule>> oldNewRuleMapping = new Hashtable<String, List<Rule>>(); List<Rule> newRules; List<Rule> newRuleMapping = null; try { for (Rule rule : factsAndRules.values()) { newRuleMapping = null; switch (rule.getRuleType()) { case STRICT: newRules = removeDefeater_transformRule(rule); rulesToAdd.addAll(newRules); rulesToDelete.add(rule.getLabel()); newRuleMapping = newRules; break; case DEFEASIBLE: if (rule.getHeadLiterals().size() > 1) throw new TheoryException(ErrorMessage.THEORY_NOT_IN_REGULAR_FORM_MULTIPLE_HEADS_RULE,new Object[]{rule.getLabel()}); // Messages.getErrorMessage(ErrorMessage.THEORY_NOT_IN_REGULAR_FORM_MULTIPLE_HEADS)); newRules = removeDefeater_transformRule(rule); rulesToDelete.add(rule.getLabel()); rulesToAdd.addAll(newRules); newRuleMapping = newRules; break; case DEFEATER: Rule r = removeDefeater_transformDefeater(rule); rulesToAdd.add(r); rulesToDelete.add(rule.getLabel()); break; default: } if (newRuleMapping != null) oldNewRuleMapping.put(rule.getLabel(), newRuleMapping); } theory.updateTheory(rulesToAdd, rulesToDelete, oldNewRuleMapping); } catch (TheoryException e) { throw new TheoryNormalizerException(getClass(), ErrorMessage.TRANSFORMATION_DEFEATER_REMOVAL_ERROR, "Defeater removal exception!", e); } } private Rule removeDefeater_transformDefeater(Rule origRule) throws TheoryNormalizerException { if (origRule.getRuleType() != RuleType.DEFEATER) return null; List<Literal> origHeadLiterals = origRule.getHeadLiterals(); if (origHeadLiterals.size() > 1) throw new TheoryNormalizerException(getClass(), "rule head contains more than 1 literal"); Literal origHeadLiteral = origHeadLiterals.get(0); Mode dummyLiteralMode = origHeadLiteral.getMode(); Mode ruleMode = origRule.getMode(); if ("".equals(dummyLiteralMode.getName())) dummyLiteralMode = ruleMode; String sign = (origHeadLiteral.isNegation()) ? "+" : "-"; Rule newRule = DomUtilities.getRule(origRule.getLabel(), RuleType.DEFEASIBLE); newRule.setOriginalLabel(origRule.getOriginalLabel()); newRule.setMode(ruleMode); try { addBodyLiterals(newRule, origRule.getBodyLiterals(), ""); newRule.addHeadLiteral(DomUtilities.getLiteral(origHeadLiteral.getName() + sign, true, dummyLiteralMode,null, (String[]) null, true)); } catch (Exception e) { } return newRule; } private List<Rule> removeDefeater_transformRule(Rule origRule) throws TheoryNormalizerException { List<Literal> origBodyLiterals = origRule.getBodyLiterals(); List<Literal> origHeadLiterals = origRule.getHeadLiterals(); if (origHeadLiterals.size() > 1) throw new TheoryNormalizerException(getClass(), "rule head contains more than 1 literal"); List<Rule> newRules = new ArrayList<Rule>(); Literal origHeadLiteral = origHeadLiterals.get(0); Mode dummyLiteralMode = origHeadLiteral.getMode(); Mode ruleMode = origRule.getMode(); if ("".equals(dummyLiteralMode.getName())) dummyLiteralMode = ruleMode; Literal newHeadLiteral = null; String[] sign = new String[2]; if (origHeadLiteral.isNegation()) { sign[0] = "-"; sign[1] = "+"; newHeadLiteral = origHeadLiteral.getComplementClone(); } else { sign[0] = "+"; sign[1] = "-"; newHeadLiteral = origHeadLiteral.clone(); } String originalRuleLabel=origRule.getOriginalLabel(); Literal dummyLiteral1 = DomUtilities.getLiteral(newHeadLiteral.getName() + sign[0], false, dummyLiteralMode,null, null, true); Literal dummyLiteral2 = DomUtilities.getLiteral(newHeadLiteral.getName() + sign[1], true, dummyLiteralMode,null, null, true); Rule newRule1 = DomUtilities.getRule(origRule.getLabel() + sign[0], origRule.getRuleType()); newRule1.setOriginalLabel(originalRuleLabel); newRule1.setMode(ruleMode); try { addBodyLiterals(newRule1, origBodyLiterals, ""); newRule1.addHeadLiteral(dummyLiteral1); } catch (Exception e) { e.printStackTrace(); } Rule newRule2 = DomUtilities.getRule(origRule.getLabel() + sign[1], origRule.getRuleType()); newRule2.setOriginalLabel(originalRuleLabel); newRule2.setMode(ruleMode); try { addBodyLiterals(newRule2, origBodyLiterals, ""); newRule2.addHeadLiteral(dummyLiteral2); } catch (Exception e) { e.printStackTrace(); } Rule newRule3 = DomUtilities.getRule(origRule.getLabel(), origRule.getRuleType()); newRule3.setOriginalLabel(originalRuleLabel); newRule3.setMode(ruleMode); try { newRule3.addBodyLiteral(dummyLiteral1); newRule3.addHeadLiteral(origHeadLiteral.clone()); } catch (Exception e) { e.printStackTrace(); } newRules.add(newRule1); newRules.add(newRule2); newRules.add(newRule3); return newRules; } public void addTheoryNormalizerListener(TheoryNormalizerListener listener) { addAppModuleListener(listener); } public void removeTheoryNormalizerListener(TheoryNormalizerListener listener) { removeAppModuleListener(listener); } protected void fireTheoryNormalizerMessage(MessageType messageType,String messageTag, Object... args) { if (hasAppModuleListeners()){ String message=Messages.getSystemMessage(messageTag, args); for (AppModuleListener listener : getAppModuleListeners()) { if (listener instanceof TheoryNormalizerListener) { ((TheoryNormalizerListener) listener).onTheoryNormalizerMessage(messageType,message); } } } } protected abstract void transformTheoryToRegularFormImpl() throws TheoryNormalizerException; }