Skip to content

Commit

Permalink
More detailed reporting of the rule parsing errors.
Browse files Browse the repository at this point in the history
  • Loading branch information
agudys authored Mar 1, 2024
1 parent 390c32d commit 1f93637
Show file tree
Hide file tree
Showing 3 changed files with 249 additions and 40 deletions.
2 changes: 1 addition & 1 deletion adaa.analytics.rules/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ codeQuality {
}

sourceCompatibility = 1.8
version = '1.7.5'
version = '1.7.6'


jar {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@

import com.rapidminer.operator.ports.metadata.AttributeMetaData;
import com.rapidminer.operator.ports.metadata.ExampleSetMetaData;
import org.apache.commons.lang.math.NumberUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -39,45 +41,50 @@ public class RuleParser {
*/
public static Rule parseRule(String s, ExampleSetMetaData meta) {
Rule rule = null;
Pattern pattern = Pattern.compile("IF\\s+(?<premise>.+)\\s+THEN(?<consequence>\\s+.*|\\s*)");
Matcher matcher = pattern.matcher(s);
boolean isSurvival = false;

Pattern pattern = Pattern.compile("IF\\s+(?<premise>.+)\\s+THEN(?<consequence>\\s+.*|\\s*)");
Matcher matcher = pattern.matcher(s);

boolean isSurvival = false;
if (meta.getAttributeByRole(SurvivalRule.SURVIVAL_TIME_ROLE) != null) {
isSurvival = true;
}

if (matcher.find()) {
String pre = matcher.group("premise");
String con = matcher.group("consequence");

ElementaryCondition consequence;
CompoundCondition premise = parseCompoundCondition(pre, meta);

if (con == null || con.trim().length() == 0) {
if (!meta.getLabelMetaData().isNumerical())
throw new IllegalArgumentException("Empty conclusion for non-numeric label attribute");
consequence = new ElementaryCondition();
consequence.attribute = meta.getLabelMetaData().getName();
consequence.valueSet = new SingletonSet(NaN, null);
consequence.adjustable = false;
consequence.disabled = false;

if (matcher.find()) {
String pre = matcher.group("premise");
String con = matcher.group("consequence");

ElementaryCondition consequence = null;
CompoundCondition premise = parseCompoundCondition(pre, meta);

if (con == null || con.trim().length() == 0) {
if (!meta.getLabelMetaData().isNumerical()) {
Logger.log("Empty conclusion for nominal label"+ "\n", Level.WARNING);
} else {
consequence = new ElementaryCondition();
consequence.attribute = meta.getLabelMetaData().getName();
consequence.valueSet = new SingletonSet(NaN, null);
consequence.adjustable = false;
consequence.disabled = false;
}
} else {
consequence = parseElementaryCondition(con, meta);
}

if (premise == null || consequence == null) {
return null;
}

rule = meta.getLabelMetaData().isNominal()
? new ClassificationRule(premise, consequence)
: (isSurvival

if (premise != null && consequence != null) {

rule = meta.getLabelMetaData().isNominal()
? new ClassificationRule(premise, consequence)
: (isSurvival
? new SurvivalRule(premise, consequence)
: new RegressionRule(premise, consequence));
}

}
}

if (rule == null) {
Logger.log("Omitting expert's knowledge entry: " + s + "\n", Level.WARNING);
}

return rule;
}

Expand Down Expand Up @@ -143,6 +150,10 @@ public static ElementaryCondition parseElementaryCondition(String s, ExampleSetM
IValueSet valueSet = null;

AttributeMetaData attributeMeta = meta.getAttributeByName(attribute);
if (attributeMeta == null) {
Logger.log("Attribute <" + attribute + "> not found"+ "\n", Level.WARNING);
return null;
}

ConditionBase.Type type = (numBrackets == 0) ? ConditionBase.Type.NORMAL :
((numBrackets == 1) ? ConditionBase.Type.PREFERRED : ConditionBase.Type.FORCED);
Expand All @@ -159,7 +170,8 @@ public static ElementaryCondition parseElementaryCondition(String s, ExampleSetM
mapping.addAll(attributeMeta.getValueSet());
double v = mapping.indexOf(value);
if (v == -1) {
return null;
Logger.log("Invalid value <" + value + "> of the nominal attribute <" + attribute + ">"+ "\n", Level.WARNING);
return null;
}
valueSet = new SingletonSet(v, mapping);

Expand All @@ -180,14 +192,36 @@ public static ElementaryCondition parseElementaryCondition(String s, ExampleSetM
matcher = regex.matcher(valueString);

if (matcher.find()) {

String lo = matcher.group("lo");
String hi = matcher.group("hi");

valueSet = new Interval(
lo.equals("-inf") ? Interval.MINUS_INF : Double.parseDouble(lo),
hi.equals("inf")? Interval.INF : Double.parseDouble(hi),
leftClosed, rightClosed);
}

double numLo = Double.NaN;
double numHi = Double.NaN;

if (lo.equals("-inf")) {
numLo = Interval.MINUS_INF;
} else if (NumberUtils.isNumber(lo)) {
numLo = Double.parseDouble(lo);
} else {
Logger.log("Invalid lower interval bound: " + lo + "\n" , Level.WARNING);
return null;
}

if (hi.equals("inf")) {
numHi = Interval.INF;
} else if (NumberUtils.isNumber(hi)) {
numHi = Double.parseDouble(hi);
} else {
Logger.log("Invalid upper interval bound: " + hi + "\n", Level.WARNING );
return null;
}

valueSet = new Interval(numLo, numHi, leftClosed, rightClosed);
} else {
Logger.log("Invalid interval: " + valueString, Level.WARNING );
return null;
}
}
}

Expand All @@ -196,8 +230,11 @@ public static ElementaryCondition parseElementaryCondition(String s, ExampleSetM
out.setType(type);
out.setAdjustable(adjustable);
}
}
} else {
Logger.log("Invalid elementary condition: " + s + "\n", Level.WARNING );
}

return out;
}

}
172 changes: 172 additions & 0 deletions examples/guider-errors.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?xml version="1.0"?>
<experiment>
<parameter_sets>

<!--=======================================================================================================================-->

<parameter_set name="illegal attribute">
<param name="use_expert">true</param>
<param name ="expert_rules">
<entry name="rule-0">IF [[gimpul = (-inf, 750)]] THEN class = {0}</entry>
</param>
<param name ="expert_preferred_conditions">
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

<!--=======================================================================================================================-->

<parameter_set name="illegal_class_value">
<param name="use_expert">true</param>
<param name ="expert_rules">
</param>
<param name ="expert_preferred_conditions">
<entry name="preferred-attribute-0">1: IF [[gimpuls = Any]] THEN class = {14}</entry>
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

<!--=======================================================================================================================-->

<parameter_set name="illegal_attribute_value">
<param name="use_expert">true</param>
<param name ="expert_rules">
</param>
<param name ="expert_preferred_conditions">
<entry name="preferred-condition-01">inf: IF [[seismic = {q}]] THEN class = {0}</entry>
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

<!--=======================================================================================================================-->

<parameter_set name="illegal_equality">
<param name="use_expert">true</param>
<param name ="expert_rules">
</param>
<param name ="expert_preferred_conditions">
<entry name="preferred-condition-01">inf: IF [[seismic - {q}]] THEN class = {0}</entry>
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

<!--=======================================================================================================================-->

<parameter_set name="illegal_if_then">
<param name="use_expert">true</param>
<param name ="expert_rules">
</param>
<param name ="expert_preferred_conditions">
<entry name="preferred-condition-01">inf: IFF [[seismic = {a}]] THEN class = {0}</entry>
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

<!--=======================================================================================================================-->

<parameter_set name="illegal_interval_comma">
<param name="use_expert">true</param>
<param name ="expert_rules">
<entry name="rule-0">IF [[gimpuls = (-inf 750)]] THEN class = {0}</entry>
</param>
<param name ="expert_preferred_conditions">
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

<!--=======================================================================================================================-->

<parameter_set name="illegal_interval_no_left">
<param name="use_expert">true</param>
<param name ="expert_rules">
<entry name="rule-0">IF [[gimpuls = -inf, 750)]] THEN class = {0}</entry>
</param>
<param name ="expert_preferred_conditions">
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

<!--=======================================================================================================================-->

<parameter_set name="illegal_interval_no_right">
<param name="use_expert">true</param>
<param name ="expert_rules">
<entry name="rule-0">IF [[gimpuls = (-inf, 750]] THEN class = {0}</entry>
</param>
<param name ="expert_preferred_conditions">
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

<!--=======================================================================================================================-->

<parameter_set name="illegal_lowerbound">
<param name="use_expert">true</param>
<param name ="expert_rules">
<entry name="rule-0">IF [[gimpuls = (-inff, 750)]] THEN class = {0}</entry>
</param>
<param name ="expert_preferred_conditions">
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

<!--=======================================================================================================================-->

<parameter_set name="illegal_upperbound">
<param name="use_expert">true</param>
<param name ="expert_rules">
<entry name="rule-0">IF [[gimpuls = (-inf, a750)]] THEN class = {0}</entry>
</param>
<param name ="expert_preferred_conditions">
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

<!--=======================================================================================================================-->

<parameter_set name="illegal_upperbound_2">
<param name="use_expert">true</param>
<param name ="expert_rules">
<entry name="rule-0">IF [[gimpuls = (-inf, 0.5.4)]] THEN class = {0}</entry>
</param>
<param name ="expert_preferred_conditions">
</param>
<param name ="expert_forbidden_conditions">
</param>
</parameter_set>

</parameter_sets>

<datasets>
<dataset>
<label>class</label>
<out_directory>./results-guider/errors</out_directory>

<training>
<report_file>training.txt</report_file>

<train>
<in_file>../data/seismic-bumps/seismic-bumps.arff</in_file>
<model_file>seismic-bumps-full.mdl</model_file>
</train>

</training>

<prediction>

</prediction>


</dataset>
</datasets>
</experiment>

0 comments on commit 1f93637

Please sign in to comment.