use of org.knime.base.node.mine.decisiontree2.PMMLSimplePredicate in project knime-core by knime.
the class RuleSetToTable method handleSurrogate.
/**
* (This is a recursive method.)
*
* @param cp A SURROGATE {@link PMMLCompoundPredicate}.
* @param predicates The predicates to be converted.
* @param usePrecedence Should we simplify the condition?
* @param parentOperator The parent operator's (logical connective) type, used for precedence, can be {@code null}.
* @param types The type of input columns.
* @return Converted {@code cp}.
* @throws IllegalStateException If cannot be transformed.
*/
private static String handleSurrogate(final PMMLCompoundPredicate cp, final List<PMMLPredicate> predicates, final boolean usePrecedence, final PMMLBooleanOperator parentOperator, final Map<String, DataType> types) {
// surrogate(a, b) = if not missing(a) then rel(a) else b = ((NOT MISSING a) AND rel(a)) OR ((MISSING a) AND b)
// surrogate(a, surrogate(b, c)) = if not missing(a) then rel(a) else if not missing(b) then rel(b) else c =
// ((NOT MISSING a) AND rel(a)) OR ((MISSING a) AND (((NOT MISSING b) AND rel(b)) OR ((MISSING b) AND rel(c))))
PMMLPredicate first = predicates.get(0);
List<PMMLPredicate> rest = predicates.subList(1, predicates.size());
if (predicates.size() == 1) {
return convertToStringPrecedence(first, usePrecedence, PMMLBooleanOperator.AND, types);
}
CheckUtils.checkState(first instanceof PMMLTruePredicate || first instanceof PMMLFalsePredicate || first instanceof PMMLSimplePredicate || first instanceof PMMLSimpleSetPredicate, "Compound predicates are not supported by the SURROGATE transformation: " + first + " in\n" + cp);
if (first instanceof PMMLFalsePredicate || first instanceof PMMLTruePredicate) {
return convertToString(first, usePrecedence, types);
}
if (first instanceof PMMLSimplePredicate || first instanceof PMMLSimpleSetPredicate) {
return parentheses(!usePrecedence || (parentOperator != null && parentOperator != PMMLBooleanOperator.OR), parentheses(!usePrecedence, /*OR is outside of this AND*/
"NOT MISSING " + dollars(first.getSplitAttribute()) + " AND " + convertToStringPrecedence(first, usePrecedence, PMMLBooleanOperator.AND, types)) + " OR " + parentheses(!usePrecedence, /*OR is outside of this AND*/
"MISSING " + dollars(first.getSplitAttribute()) + " AND " + handleSurrogate(cp, rest, usePrecedence, PMMLBooleanOperator.AND, types)));
}
throw new IllegalStateException("Compound predicates are not supported at this position: " + first + " in\n" + cp);
}
use of org.knime.base.node.mine.decisiontree2.PMMLSimplePredicate in project knime-core by knime.
the class FromDecisionTreeNodeModel method addRules.
/**
* Adds the rules to {@code rs} (recursively on each leaf).
*
* @param rs The output {@link RuleSet}.
* @param parents The parent stack.
* @param node The actual node.
*/
private void addRules(final RuleSet rs, final List<DecisionTreeNode> parents, final DecisionTreeNode node) {
if (node.isLeaf()) {
SimpleRule rule = rs.addNewSimpleRule();
if (m_rulesToTable.getScorePmmlRecordCount().getBooleanValue()) {
// This increases the PMML quite significantly
BigDecimal sum = BigDecimal.ZERO;
final MathContext mc = new MathContext(7, RoundingMode.HALF_EVEN);
final boolean computeProbability = m_rulesToTable.getScorePmmlProbability().getBooleanValue();
if (computeProbability) {
sum = new BigDecimal(node.getClassCounts().entrySet().stream().mapToDouble(e -> e.getValue().doubleValue()).sum(), mc);
}
for (final Entry<DataCell, Double> entry : node.getClassCounts().entrySet()) {
final ScoreDistribution scoreDistrib = rule.addNewScoreDistribution();
scoreDistrib.setValue(entry.getKey().toString());
scoreDistrib.setRecordCount(entry.getValue());
if (computeProbability) {
if (Double.compare(entry.getValue().doubleValue(), 0.0) == 0) {
scoreDistrib.setProbability(new BigDecimal(0.0));
} else {
scoreDistrib.setProbability(new BigDecimal(entry.getValue().doubleValue(), mc).divide(sum, mc));
}
}
}
}
CompoundPredicate and = rule.addNewCompoundPredicate();
and.setBooleanOperator(BooleanOperator.AND);
DecisionTreeNode n = node;
do {
PMMLPredicate pmmlPredicate = ((DecisionTreeNodeSplitPMML) n.getParent()).getSplitPred()[n.getParent().getIndex(n)];
if (pmmlPredicate instanceof PMMLSimplePredicate) {
PMMLSimplePredicate simple = (PMMLSimplePredicate) pmmlPredicate;
SimplePredicate predicate = and.addNewSimplePredicate();
copy(predicate, simple);
} else if (pmmlPredicate instanceof PMMLCompoundPredicate) {
PMMLCompoundPredicate compound = (PMMLCompoundPredicate) pmmlPredicate;
CompoundPredicate predicate = and.addNewCompoundPredicate();
copy(predicate, compound);
} else if (pmmlPredicate instanceof PMMLSimpleSetPredicate) {
PMMLSimpleSetPredicate simpleSet = (PMMLSimpleSetPredicate) pmmlPredicate;
copy(and.addNewSimpleSetPredicate(), simpleSet);
} else if (pmmlPredicate instanceof PMMLTruePredicate) {
and.addNewTrue();
} else if (pmmlPredicate instanceof PMMLFalsePredicate) {
and.addNewFalse();
}
n = n.getParent();
} while (n.getParent() != null);
// Simple fix for the case when a single condition was used.
while (and.getFalseList().size() + and.getCompoundPredicateList().size() + and.getSimplePredicateList().size() + and.getSimpleSetPredicateList().size() + and.getTrueList().size() < 2) {
and.addNewTrue();
}
if (m_rulesToTable.getProvideStatistics().getBooleanValue()) {
rule.setNbCorrect(node.getOwnClassCount());
rule.setRecordCount(node.getEntireClassCount());
}
rule.setScore(node.getMajorityClass().toString());
} else {
parents.add(node);
for (int i = 0; i < node.getChildCount(); ++i) {
addRules(rs, parents, node.getChildAt(i));
}
parents.remove(node);
}
}
use of org.knime.base.node.mine.decisiontree2.PMMLSimplePredicate in project knime-core by knime.
the class FromDecisionTreeNodeModel method copy.
/**
* Copies the {@code predicate} to {@code compound}.
*
* @param predicate A PMML xml object for {@link CompoundPredicate}
* @param compund A KNIME domain object for {@link PMMLCompoundPredicate}.
*/
private void copy(final CompoundPredicate predicate, final PMMLCompoundPredicate compound) {
PMMLPredicateTranslator.exportTo(compound, predicate);
predicate.setBooleanOperator(PMMLPredicateTranslator.getOperator(compound.getBooleanOperator()));
for (PMMLPredicate rawPredicate : compound.getPredicates()) {
if (rawPredicate instanceof PMMLSimplePredicate) {
PMMLSimplePredicate sp = (PMMLSimplePredicate) rawPredicate;
copy(predicate.addNewSimplePredicate(), sp);
} else if (rawPredicate instanceof PMMLCompoundPredicate) {
PMMLCompoundPredicate cp = (PMMLCompoundPredicate) rawPredicate;
copy(predicate.addNewCompoundPredicate(), cp);
} else if (rawPredicate instanceof PMMLSimpleSetPredicate) {
PMMLSimpleSetPredicate ssp = (PMMLSimpleSetPredicate) rawPredicate;
copy(predicate.addNewSimpleSetPredicate(), ssp);
} else if (rawPredicate instanceof PMMLTruePredicate) {
predicate.addNewTrue();
} else if (rawPredicate instanceof PMMLFalsePredicate) {
predicate.addNewFalse();
}
}
}
use of org.knime.base.node.mine.decisiontree2.PMMLSimplePredicate in project knime-core by knime.
the class PMMLExpressionFactory method compare.
/**
* {@inheritDoc}
*/
@Override
public PMMLPredicate compare(final Expression left, final Expression right, final DataValueComparator cmp, final int... possibleValues) {
final PMMLOperator op;
if (Arrays.equals(possibleValues, LT)) {
op = PMMLOperator.LESS_THAN;
} else if (Arrays.equals(possibleValues, LE)) {
op = PMMLOperator.LESS_OR_EQUAL;
} else if (Arrays.equals(possibleValues, GT)) {
op = PMMLOperator.GREATER_THAN;
} else if (Arrays.equals(possibleValues, GE)) {
op = PMMLOperator.GREATER_OR_EQUAL;
} else if (Arrays.equals(possibleValues, EQ)) {
op = PMMLOperator.EQUAL;
} else {
throw new IllegalStateException("" + Arrays.toString(possibleValues));
}
handleSameType(left, right);
if (left.getTreeType() == ASTType.ColRef) {
m_usedColumns.add(expressionToString(left));
}
if (right.getTreeType() == ASTType.ColRef) {
m_usedColumns.add(expressionToString(right));
final PMMLOperator opposite;
switch(op) {
case EQUAL:
opposite = op;
break;
case GREATER_OR_EQUAL:
opposite = PMMLOperator.LESS_OR_EQUAL;
break;
case GREATER_THAN:
opposite = PMMLOperator.LESS_THAN;
break;
case LESS_OR_EQUAL:
opposite = PMMLOperator.GREATER_OR_EQUAL;
break;
case LESS_THAN:
opposite = PMMLOperator.GREATER_THAN;
break;
default:
throw new UnsupportedOperationException("Not supported: " + op);
}
return new PMMLSimplePredicate(expressionToString(right), opposite, expressionToString(left));
}
return new PMMLSimplePredicate(expressionToString(left), op, expressionToString(right));
}
use of org.knime.base.node.mine.decisiontree2.PMMLSimplePredicate in project knime-core by knime.
the class PMMLRuleTranslator method setOperator.
/**
* Sets the operator of {@code pred} based on the properties of {@code simple.}
*
* @param pred An xml {@link SimplePredicate}.
* @param simple A {@link PMMLSimplePredicate}.
*/
private void setOperator(final SimplePredicate pred, final PMMLSimplePredicate simple) {
PMMLOperator x = simple.getOperator();
Enum e = PMMLPredicateTranslator.getOperator(x);
if (e == null) {
throw new UnsupportedOperationException("Unknown operator: " + x);
}
pred.setOperator(e);
}
Aggregations