/**
* 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.tdl;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import spindle.core.MessageType;
import spindle.core.dom.Literal;
import spindle.core.dom.Rule;
import spindle.core.dom.Temporal;
import spindle.core.dom.TheoryType;
import spindle.engine.TheoryNormalizerException;
import spindle.sys.AppConst;
import spindle.sys.AppFeatureConst;
import spindle.sys.Conf;
import spindle.sys.message.ErrorMessage;
import spindle.sys.message.SystemMessage;
/**
* TDL 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>
* <p>
* Rule/literal modal conversions and conflict resolutions are based on description presented in:
* <ul>
* <li>G. Governatori and A. Rotolo (2008) BIO Logical Agents: Norms, Beliefs, Intentions in Defeasible Logic,
* <i>Journal of Autonomous Agents and Multi Agent Systems</i>, Vol. 17 (1), pp. 36--69</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 TdlTheoryNormalizer2 extends spindle.engine.mdl.MdlTheoryNormalizer2 {
// private static final Comparator<Temporal> TEMPORAL_START_COMPARATOR = new TemporalStartComparator();
// private LiteralDataStore literalDataStore = null;
// private TreeMap<Literal, Map<Temporal, List<Literal>>> conflictTemporalLiteralsStore = null;
//private TreeMap<Literal, List<Literal>> conflictTemporalLiteralsStore = null;
private boolean isReasoningWithMixedTemporalLiterals=false;
public TdlTheoryNormalizer2() throws TheoryNormalizerException {
super();
if (AppConst.isDeploy)
throw new TheoryNormalizerException(getClass(), ErrorMessage.THEORY_NORMALIZER_NOT_SUPPORTED, new Object[] { TheoryType.TDL });
//conflictTemporalLiteralsStore = new TreeMap<Literal, List<Literal>>(new LiteralComparator(false));
isReasoningWithMixedTemporalLiterals=Conf.isReasoningWithMixedTemporalLiterals();
}
// @Override
// protected void verifyConflictRules() throws TheoryNormalizerException {
// List<Superiority> superiorities = theory.getAllSuperiority();
// for (Superiority superiority : superiorities) {
// String superiorRuleId = superiority.getSuperior();
// String inferiorRuleId = superiority.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 });
//
// boolean isConflictRule = false;
// List<Literal> superiorRuleHead = superiorRule.getHeadLiterals();
// List<Literal> inferiorRuleHead = inferiorRule.getHeadLiterals();
//
// for (int j = 0; !isConflictRule && j < superiorRuleHead.size(); j++) {
// Literal superiorHead = superiorRuleHead.get(j);
// boolean superiorHeadHasTemporal = superiorHead.hasTemporalInfo();
// Temporal superiorHeadTemporal = superiorHead.getTemporal();
// Set<Literal> conflictLiterals = getConflictLiterals(superiorHead);
// if (!AppConst.isDeploy)
// System.out.println("TdlTheoryNormalizer2.verifyConflictRules: superiorHead=" + superiorRuleHead.get(j)
// + ", conflictLiterals=" + conflictLiterals);
// for (int i = 0; !isConflictRule && i < inferiorRuleHead.size(); i++) {
// Literal inferiorHead = inferiorRuleHead.get(i);
// boolean inferiorHeadHasTemporal = inferiorHead.hasTemporalInfo();
// Temporal inferiorHeadTemporal = inferiorHead.getTemporal();
//
// Literal plainInferiorHead=DomUtilities.getPlainLiteral(inferiorHead);
// boolean hasConflictPlainHeads = conflictLiterals.contains(plainInferiorHead);
// if (!AppConst.isDeploy) System.out.println(" hasConflictPlainHeads=" + hasConflictPlainHeads);
//
// // continue checking next head literal if the current literal is not in conflict with the superior head literal.
// if (!hasConflictPlainHeads) continue;
//
// // if both the superior rule head and inferior rule head are of temporal literals,
// // then check whether the inferior rule head (without temporal info) appears in the conflict
// // literals set or not.
// // if yes, then check whether the temporal of the two head's literals overlapped each other.
// // if yes, then are conflicting rules; or not otherwise.
// if (superiorHeadHasTemporal && inferiorHeadHasTemporal){
// if (superiorHeadTemporal.isIntersect(inferiorHeadTemporal) )
// isConflictRule=true;
//// if (superiorHeadTemporal.isIntersect(inferiorHeadTemporal) && !superiorHeadTemporal.meet(inferiorHeadTemporal))
//// isConflictRule = true;
// } else if (!(superiorHeadHasTemporal || inferiorHeadHasTemporal)){
// isConflictRule=true;
// } else{
// if (!isReasoningWithMixedTemporalLiterals)
// throw new TheoryNormalizerException(getClass(),ErrorMessage.THEORY_NORMALIZER_PLAIN_AND_TEMPORAL_FORM_OF_SAME_LITERAL_APPEAR_IN_CONFLICTING_HEADS,new Object[]{plainInferiorHead,superiorRuleId,inferiorRuleId});
//
// fireTheoryNormalizerMessage(MessageType.WARNING,SystemMessage.THEORY_NORMALIZER_PLAIN_AND_TEMPORAL_FORM_OF_SAME_LITERAL_APPEAR_IN_CONFLICTING_HEADS,new Object[]{plainInferiorHead,superiorRuleId,inferiorRuleId});
// isConflictRule = true;
// }
//
//// if (superiorHeadHasTemporal) {
//// if (inferiorHeadHasTemporal) {
//// if (superiorHeadTemporal.isIntersect(inferiorHeadTemporal) && !superiorHeadTemporal.meet(inferiorHeadTemporal))
//// isConflictRule = true;
//// } else {
//// isConflictRule = true;
//// fireTheoryNormalizerMessage(MessageType.WARNING, "plain and temporal Literal [" + superiorRuleHead + "," + inferiorRuleHead+"] appeared");
//// }
//// } else {
//// if (inferiorHeadHasTemporal) {
//// isConflictRule = true;
//// fireTheoryNormalizerMessage(MessageType.WARNING, "plain and temporal Literal [" + superiorRuleHead + "," + inferiorRuleHead+"] appeared");
//// } else {
//// //if (conflictLiterals.contains(inferiorRuleHead.get(i))) isConflictRule = true;
//// isConflictRule = true;
//// }
//// }
//
// // if (superiorHead.hasTemporalInfo() && inferiorHead.hasTemporalInfo()) {
// // // if (null!=superiorHeadTemporal && null!=inferiorHeadTemporal){
// // Literal conflictHead = conflictLiterals.floor(inferiorRuleHead.get(i));
// // if (null != conflictHead) {
// // if (superiorHeadTemporal.isIntersect(inferiorHeadTemporal) //
// // && !superiorHeadTemporal.meet(inferiorHeadTemporal)) isConflictRule = true;
// // // if (superiorHead.getTemporal().isIntersect(inferiorHead.getTemporal())) isConflictRule =
// // // true;
// // }
// // } else if (!superiorHead.hasTemporalInfo() && !inferiorHead.hasTemporalInfo()) {
// // if (conflictLiterals.contains(inferiorRuleHead.get(i))) isConflictRule = true;
// // }
// if (!AppConst.isDeploy)
// System.out.println(" checking inferior rule head:" + inferiorRuleHead.get(i) + ", isConflictRule="
// + isConflictRule);
// }
// }
// if (!isConflictRule) { throw new TheoryNormalizerException(getClass(), ErrorMessage.SUPERIORITY_UNCONFLICTING_RULES,
// new Object[] { superiorRuleId, inferiorRuleId }); }
// }
// }
@Override
protected boolean isConflictRules(Rule r1, Rule r2) throws TheoryNormalizerException {
logMessage(Level.FINER, 1, "verify conflict rules", r1.getLabel(), r2.getLabel());
boolean isConflictRule = false;
List<Literal> r1Heads = r1.getHeadLiterals();
List<Literal> r2Heads = r2.getHeadLiterals();
for (int j = 0; !isConflictRule && j < r1Heads.size(); j++) {
Literal r1Head = r1Heads.get(j);
boolean r1HeadHasTemporal = r1Head.hasTemporalInfo();
Temporal r1HeadTemporal = r1Head.getTemporal();
Set<Literal> conflictLiterals = getConflictLiterals(r1Head);
if (!AppConst.isDeploy)
System.out.println("TdlTheoryNormalizer2.verifyConflictRules: superiorHead=" + r1Head // r1Heads.get(j)
+ ", conflictLiterals=" + conflictLiterals);
for (int i = 0; !isConflictRule && i < r2Heads.size(); i++) {
Literal r2Head = r2Heads.get(i);
boolean r2HeadHasTemporal = r2Head.hasTemporalInfo();
Temporal r2HeadTemporal = r2Head.getTemporal();
Literal plainInferiorHead=r2Head.cloneWithNoTemporal();
boolean hasConflictPlainLiteralHeads = conflictLiterals.contains(plainInferiorHead);
if (!AppConst.isDeploy) System.out.println(" hasConflictPlainLiteralHeads=" + hasConflictPlainLiteralHeads);
// continue checking next head literal if the two head literals (in plain form) are not conflicting each others.
if (!hasConflictPlainLiteralHeads) continue;
// if the two head literals (in plain form) are conflicting each others, return true either:
// Case 1: when considering superiority relation with same start temporals only
// (1) the two temporals are having the same start time; or
// (2) if one of the literals is plain literal, then check whether it holds at -ve inf.
// Case 2: Otherwise
// (1) the temporals of the two literals are overlapping each others; or
// (2) one of them is a temporal literal and the other is an ordinary literal.
if (r1HeadHasTemporal && r2HeadHasTemporal) {
if (AppFeatureConst.superiorityWithSameStartTemporalOnly) {
if (r1HeadTemporal.sameStart(r2HeadTemporal)) isConflictRule = true;
} else if (r1HeadTemporal.overlap(r2HeadTemporal)) isConflictRule = true;
} else if (!(r1HeadHasTemporal || r2HeadHasTemporal)) {
isConflictRule = true;
} else {
if (!isReasoningWithMixedTemporalLiterals)
throw new TheoryNormalizerException(getClass(),
ErrorMessage.THEORY_NORMALIZER_PLAIN_AND_TEMPORAL_FORM_OF_SAME_LITERAL_APPEAR_IN_CONFLICTING_HEADS,
new Object[] { plainInferiorHead, r1.getLabel(), r2.getLabel() });
fireTheoryNormalizerMessage(MessageType.WARNING,
SystemMessage.THEORY_NORMALIZER_PLAIN_AND_TEMPORAL_FORM_OF_SAME_LITERAL_APPEAR_IN_CONFLICTING_HEADS,
new Object[] { plainInferiorHead, r1.getLabel(), r2.getLabel() });
if (AppFeatureConst.superiorityWithSameStartTemporalOnly){
if (r1HeadHasTemporal){
if (Long.MIN_VALUE==r1HeadTemporal.getStartTime())isConflictRule=true;
} else {
if (Long.MIN_VALUE==r2HeadTemporal.getStartTime())isConflictRule=true;
}
} else isConflictRule = true;
}
// if (!AppConst.isDeploy)
// System.out.println(" check rule head:"+r1Head+"," + r2Head + " :- isConflictRule=" + isConflictRule);
logMessage(Level.FINEST, 2, "verify conflict literals", r1Head, r2Head, "isConflictRule=" + isConflictRule);
}
}
return isConflictRule;
}
// /**
// * transform the theory to regular form and defeasible rules with multiple heads to single headed rules.
// */
// @Override
// protected void transformTheoryToRegularFormImpl() throws TheoryNormalizerException {
// try {
// literalDataStore = new LiteralDataStore(theory);
// conflictTemporalLiteralsStore = new TreeMap<Literal, Map<Temporal, List<Literal>>>(new LiteralComparator(false));
//
// super.transformTheoryToRegularFormImpl();
// } catch (LiteralDataStoreException e) {
// throw new TheoryNormalizerException(getClass(), e);
// }finally{
// literalDataStore=null;
// if (null!=conflictTemporalLiteralsStore) {
// conflictTemporalLiteralsStore.clear();
// conflictTemporalLiteralsStore=null;
// }
// }
// }
// protected List<Literal> getConflictLiterals(Literal literal) {
// if (literal.hasTemporalInfo()) {
// Map<Temporal, List<Literal>> temporalSet = conflictTemporalLiteralsStore.get(literal);
// if (null == temporalSet) {
// temporalSet = new TreeMap<Temporal, List<Literal>>(TEMPORAL_START_COMPARATOR);
// conflictTemporalLiteralsStore.put(literal, temporalSet);
// }
// Temporal temporal = literal.getTemporal();
// List<Literal> conflictLiterals = temporalSet.get(temporal);
// if (null == conflictLiterals) {
// Set<Literal> conflictLiteralsSet = new TreeSet<Literal>();
// Set<Literal> relatedLiterals = literalDataStore.getRelatedTemporalLiterals(literal);
// Set<Literal> relatedConflictLiterals = literalDataStore.getRelatedTemporalLiterals(literal.getComplementClone());
//
// System.out.println(getClass().getCanonicalName() + ".relatedLiteral(" + literal + ")=" + relatedLiterals);
// System.out.println(getClass().getCanonicalName() + ".relatedConflictLiterals(" + literal + ")=" +
// relatedConflictLiterals);
//
// for (Literal relatedLiteral : relatedLiterals) {
// conflictLiteralsSet.addAll(theory.getConflictLiterals(relatedLiteral));
// }
// for (Literal relatedConflictLiteral : relatedConflictLiterals) {
// conflictLiteralsSet.addAll(theory.getConflictLiterals(relatedConflictLiteral.getComplementClone()));
// }
// conflictLiterals = new Vector<Literal>(conflictLiteralsSet);
// temporalSet.put(temporal, conflictLiterals);
// }
// System.out.println(getClass().getCanonicalName() + ".getConflictLiterals(" + literal + ")=" + conflictLiterals);
// return conflictLiterals;
// // return new TreeSet<Literal>(theory.getConflictLiterals(literal));
// } else {
// return theory.getConflictLiterals(literal);
// }
// }
}