/**
* 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.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;
import spindle.core.dom.DomUtilities;
import spindle.core.dom.Literal;
import spindle.core.dom.Rule;
import spindle.core.dom.RuleException;
import spindle.core.dom.RuleType;
import spindle.engine.TheoryNormalizer;
import spindle.engine.TheoryNormalizerException;
import spindle.sys.AppConst;
import spindle.sys.message.ErrorMessage;
/**
* SDL Theory Normalizer.
* <p>
* Provides methods that can be used to transform a defeasible theory into an equivalent theory without superiority
* relation or defeater using the algorithms described in:
* <ul>
* <li>G. Antoniou, D. Billington, G. Governatori and M.J. Maher (2001) Representation Results for Defeasible Logic,
* <i>ACM Transactions on Computational Logic</i>, Vol. 2 (2), pp. 255-287</li>
* </ul>
* </p>
*
* @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory
* @since version 1.0.0
* @version Last modified 2012.07.21
*/
public class SdlTheoryNormalizer extends TheoryNormalizer {
public SdlTheoryNormalizer() {
super();
}
/**
* expand defeasible rule with head more than one literal, for example:
*
* <pre>
* a => b,c
* </pre>
*
* will becomes
*
* <pre>
* a => b
* a, -b => c
* </pre>
*
* @param rule
* original defeasible rule
* @return list of expanded rules
* @throws RuleException
*/
protected List<Rule> expandDefeasibleRule(final Rule rule) throws RuleException {
if (rule.getRuleType() != RuleType.DEFEASIBLE) return null;
String originalRuleLabel=rule.getOriginalLabel();
List<Rule> newRules = new ArrayList<Rule>();
List<Literal> headLiterals = rule.getHeadLiterals();
try {
if (headLiterals.size() < 2) {
Rule newRule = rule.clone();
newRules.add(newRule);
} else {
List<Literal> bodyLiterals = rule.getBodyLiterals();
Literal lastLiteral = null;
int count = 1;
String newRuleLabel = null;
for (Literal literal : headLiterals) {
if (null == lastLiteral) {
} else {
Literal lc = lastLiteral.getComplementClone();
bodyLiterals.add(lc);
}
newRuleLabel = rule.getLabel() + "_" + count;
Rule newRule = DomUtilities.getRule(newRuleLabel, RuleType.DEFEASIBLE);
newRule.setOriginalLabel(originalRuleLabel);
addBodyLiterals(newRule, bodyLiterals, "");
newRule.addHeadLiteral(literal);
newRules.add(newRule);
lastLiteral = literal;
count++;
}
}
return newRules;
} catch (Exception e) {
throw new RuleException("exception throw while expanding rule [" + rule.getLabel() + "]", e);
}
}
/**
* transform the theory to regular form and normalize the defeasible rule to single literal head
*/
@Override
protected void transformTheoryToRegularFormImpl() throws TheoryNormalizerException {
List<Rule> rulesToAdd = new ArrayList<Rule>();
Set<String> rulesToDelete = new TreeSet<String>();
List<Literal> headLiterals = null;
List<Literal> origHeadLiterals = null;
Rule newRule1 = null;
Rule newRule2 = null;
Rule newRule3 = null;
List<Rule> newRules = null;
Map<String, List<Rule>> oldNewRuleMapping = new Hashtable<String, List<Rule>>();
try {
for (Rule rule : factsAndRules.values()) {
logMessage(Level.FINER, 1, "transforming ", rule.getRuleType().getLabel(), " [", rule.getLabel(), "]");
String originalRuleLabel=rule.getOriginalLabel();
newRule1 = null;
newRule2 = null;
newRule3 = null;
switch (rule.getRuleType()) {
case STRICT:
origHeadLiterals = rule.getHeadLiterals();
headLiterals = rule.getHeadLiterals();
String profixStr = (factsAndRules.containsKey(rule.getLabel() + TRANSFORM_POSTFIX)) ? (Utilities.getRandomString(5) + TRANSFORM_POSTFIX)
: TRANSFORM_POSTFIX;
newRule1 = DomUtilities.getRule(rule.getLabel() + profixStr, RuleType.STRICT);
newRule1.setOriginalLabel(originalRuleLabel);
addBodyLiterals(newRule1, rule.getBodyLiterals(), TRANSFORM_POSTFIX);
addHeadLiterals(newRule1, headLiterals, TRANSFORM_POSTFIX);
newRule2 = DomUtilities.getRule(rule.getLabel() + profixStr + TRANSFORM_POSTFIX2, RuleType.STRICT);
newRule2.setOriginalLabel(originalRuleLabel);
addBodyLiterals(newRule2, headLiterals, TRANSFORM_POSTFIX);
addHeadLiterals(newRule2, origHeadLiterals, "");
// change the strict rule to defeasible rule, and
// add the two new strict rules to the theory
newRule3 = rule.clone();
newRule3.setOriginalLabel(originalRuleLabel);
newRule3.setRuleType(RuleType.DEFEASIBLE);
rulesToAdd.add(newRule1);
rulesToAdd.add(newRule2);
rulesToAdd.add(newRule3);
rulesToDelete.add(rule.getLabel());
break;
case FACT:
origHeadLiterals = rule.getHeadLiterals();
headLiterals = rule.getHeadLiterals();
String newFactStrictRuleLabel = theory.getUniqueRuleLabel(FACT_RULE_TRANSFORM_PREFIX);
newRule1 = DomUtilities.getRule(newFactStrictRuleLabel, RuleType.STRICT);
newRule1.setOriginalLabel(originalRuleLabel);
addHeadLiterals(newRule1, headLiterals, TRANSFORM_POSTFIX);
newRule2 = DomUtilities.getRule(newFactStrictRuleLabel + TRANSFORM_POSTFIX, RuleType.STRICT);
newRule2.setOriginalLabel(originalRuleLabel);
addBodyLiterals(newRule2, headLiterals, TRANSFORM_POSTFIX);
addHeadLiterals(newRule2, origHeadLiterals, "");
// delete the fact, and
// add the two new strict rules to the theory
rulesToDelete.add(rule.getLabel());
rulesToAdd.add(newRule1);
rulesToAdd.add(newRule2);
break;
case DEFEASIBLE:
// expand the defeasible rule if number of head literal is
// greater than 1
// do nothing otherwise
headLiterals = rule.getHeadLiterals();
if (headLiterals.size() > 1) {
logMessage(Level.FINER, 1, "expending ", rule.getRuleType().getLabel(), " [", rule.getLabel(), "]");
newRules = expandDefeasibleRule(rule);
// delete the old rule and add the expanded rules to the theory
rulesToDelete.add(rule.getLabel());
rulesToAdd.addAll(newRules);
oldNewRuleMapping.put(rule.getLabel(), newRules);
} else {
logMessage(Level.FINER, 2, "no transform performed to ", rule.getRuleType().getLabel(), " [", rule.getLabel(), "]");
}
break;
default:
logMessage(Level.FINER, 2, "no transform performed to ", rule.getRuleType().getLabel(), " [", rule.getLabel(), "]");
}
}
theory.updateTheory(rulesToAdd, rulesToDelete, oldNewRuleMapping);
} catch (Exception e) {
throw new TheoryNormalizerException(getClass(), ErrorMessage.THEORY_UPDATE_ERROR, e);
} finally {
if (!AppConst.isDeploy) {
logMessage(Level.INFO, 0, "=== transformTheoryToRegularFormImpl - start ===");
logMessage(Level.INFO, 0, null, theory);
logMessage(Level.INFO, 0, "=== transformTheoryToRegularFormImpl - end ===");
}
}
}
}