/**
*
* Copyright 2013-15 by Szymon Bobek, Grzegorz J. Nalepa, Mateusz Ślażyński
*
*
* This file is part of HeaRTDroid.
* HeaRTDroid is a rule engine that is based on HeaRT inference engine,
* XTT2 representation and other concepts developed within the HeKatE project .
*
* HeaRTDroid is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeaRTDroid 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeaRTDroid. If not, see <http://www.gnu.org/licenses/>.
*
**/
package heart.xtt;
import heart.Action;
import heart.Debug;
import heart.Debug.Level;
import heart.WorkingMemory;
import heart.alsvfd.Formulae;
import heart.exceptions.NotInTheDomainException;
import heart.uncertainty.UncertainTrue;
import heart.uncertainty.UncertainTrueEvaluator;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
public class Rule {
/**
* This field is used by the SQL module while storing/restoring model into/from database.
* If not provided, this should be null;
*/
protected String id;
/**
* This field contains rule name. This should be the default identifier that
* rules are referred. In HMR it is usually build from two elements separated by the
* 'slash': NAME/ID. However, in this representation it is one filed.
*/
protected String name;
/**
* The certainty factor of a rule. It represents a confidence of the rule.
*/
protected float certaintyFactor;
/**
* This is a list of rules that the inference engine should proceed to after firing this rule.
*/
protected LinkedList<Rule> ruleLinks;
/**
* This is a list of rules that the inference engine should proceed to after firing this rule.
*/
protected LinkedList<Table> tabLinks;
/**
* A list that contains a list of firing conditions for the rule.
* Each condition has to be valid ALSV(FD) expression defined by the {@link Formulae}.
*/
protected LinkedList<Formulae> conditions;
/**
* List that contains decisions that has to be fired when conditions are true.
* Decision is defined by the {@link Decision} class.
*/
protected LinkedList<Decision> decisions;
/**
* List of names for the {@link Action} interface implementations that
* should be executed when the rules conditions are true.
*/
protected LinkedList<String> actions;
public Rule() {
conditions = new LinkedList<Formulae>();
decisions = new LinkedList<Decision>();
ruleLinks = new LinkedList<Rule>();
tabLinks = new LinkedList<Table>();
actions = new LinkedList<String>();
setCertaintyFactor(1.0f);
}
/**
* Method that evaluates all the rules conditions.
* It does not execute the decision part of the rule, it only evaluates the conditional part.
*
* @param wm a working memory object that contains information about attributes values
* @return true if all the rule's conditions are true, false otherwise
* @throws NotInTheDomainException
*/
public UncertainTrue evaluate(WorkingMemory wm, UncertainTrueEvaluator ute) throws NotInTheDomainException{
Debug.debug(Debug.heartTag, Level.RULES, "Checking conditions of rule "+this.getName()+" (ID: "+this.getId()+")");
try{
UncertainTrue finalResult = new UncertainTrue(1.0f); //TODO: max/min certainty
for(Formulae f : conditions){
Debug.debug(Debug.heartTag, Level.RULES, "Checking condition "+f);
UncertainTrue partialResult = f.evaluate(wm, ute);
Debug.debug(Debug.heartTag, Level.RULES,
"Condition "+f+" satisfied with certainty ("+partialResult.getCertinatyFactor()+").");
if(partialResult.getCertinatyFactor() < finalResult.getCertinatyFactor()){
finalResult = partialResult;
Debug.debug(Debug.heartTag, Level.RULES,
"Changin the rule evaluation result to be true with certainty ("+finalResult.getCertinatyFactor()+").");
}
}
return finalResult;
}catch (NotInTheDomainException e) {
// TODO Auto-generated catch block
throw e;
}
}
/**
* Method that fires the decision part of the rule.
* It does not evaluate the rule conditions.
* For that, refer to {@link #evaluate()}.
*
* @param wm a working memory object that contains information about attributes values
* @return true, if the rule was correctly executed, false if there are some errors
* @throws UnsupportedOperationException
* @throws NotInTheDomainException
*/
public boolean execute(WorkingMemory wm) throws UnsupportedOperationException, NotInTheDomainException{
try{
Debug.debug(Debug.heartTag, Level.RULES, "Executing decisinos of rule "+this.getName()+" (ID: "+this.getId()+")");
//Exeute decisions - set new attributes values
for(Decision d : decisions){
Debug.debug(Debug.heartTag, Level.RULES, "Executing decisions "+d);
if(!d.execute(wm)){
Debug.debug(Debug.heartTag, Level.RULES, "Executing decisions "+d+" failed.");
return false;
}else{
Debug.debug(Debug.heartTag, Level.RULES, "Executing decisions "+d+" succeeded.");
}
}
//Execute actions
Debug.debug(Debug.heartTag, Level.RULES, "Executing actions of rule "+this.getName()+" (ID: "+this.getId()+")");
for(String a : actions){
if(a != null){
Class<?> actionClass = Class.forName(a);
Method method = actionClass.getMethod("execute");
Action action = (Action)actionClass.newInstance();
method.invoke(action);
}
}
//TODO pass tokens, what about rule-links?
return true;
}catch(UnsupportedOperationException e){
//TODO rethrow with modified message
throw e;
} catch (NotInTheDomainException e) {
// TODO Auto-generated catch block
throw e;
} catch (InstantiationException e) {
// TODO Auto-generated catch block
return false;
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
return false;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
return false;
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
return false;
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
return false;
} catch (SecurityException e) {
// TODO Auto-generated catch block
return false;
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
return false;
}
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LinkedList<Rule> getRuleLinks() {
return ruleLinks;
}
public void setRuleLinks(LinkedList<Rule> ruleLinks) {
this.ruleLinks = ruleLinks;
}
public LinkedList<Table> getTabLinks() {
return tabLinks;
}
public void setTabLinks(LinkedList<Table> tablinks) {
this.tabLinks = tablinks;
}
public LinkedList<Formulae> getConditions() {
return conditions;
}
public void setConditions(LinkedList<Formulae> conditions) {
this.conditions = conditions;
}
public LinkedList<Decision> getDecisions() {
return decisions;
}
public void setDecisions(LinkedList<Decision> decisions) {
this.decisions = decisions;
}
public float getCertaintyFactor() {
return certaintyFactor;
}
public void setCertaintyFactor(float certaintyFactor) {
this.certaintyFactor = certaintyFactor;
}
public LinkedList<String> getActions() {
return actions;
}
public void setActions(LinkedList<String> actions) {
this.actions = actions;
}
}