/** * Push the negations all the way to just before the leaves. Also remove * double negatives. * @param root the expression to normalize * @return the normalized expression, which may share some or all of the * nodes of the original expression. */ internal static ExpressionTree pushDownNot(ExpressionTree root) { if (root.getOperator() == ExpressionTree.Operator.NOT) { ExpressionTree child = root.getChildren()[0]; switch (child.getOperator()) { case ExpressionTree.Operator.NOT: return(pushDownNot(child.getChildren()[0])); case ExpressionTree.Operator.CONSTANT: return(new ExpressionTree(child.getConstant().Value.not())); case ExpressionTree.Operator.AND: root = new ExpressionTree(ExpressionTree.Operator.OR); foreach (ExpressionTree kid in child.getChildren()) { root.getChildren().Add(pushDownNot(new ExpressionTree(ExpressionTree.Operator.NOT, kid))); } break; case ExpressionTree.Operator.OR: root = new ExpressionTree(ExpressionTree.Operator.AND); foreach (ExpressionTree kid in child.getChildren()) { root.getChildren().Add(pushDownNot(new ExpressionTree (ExpressionTree.Operator.NOT, kid))); } break; // for leaf, we don't do anything default: break; } } else if (root.getChildren() != null) { // iterate through children and push down not for each one for (int i = 0; i < root.getChildren().Count; ++i) { root.getChildren()[i] = pushDownNot(root.getChildren()[i]); } } return(root); }
/** * Remove MAYBE values from the expression. If they are in an AND operator, * they are dropped. If they are in an OR operator, they kill their parent. * This assumes that pushDownNot has already been called. * @param expr The expression to clean up * @return The cleaned up expression */ internal static ExpressionTree foldMaybe(ExpressionTree expr) { if (expr.getChildren() != null) { for (int i = 0; i < expr.getChildren().Count; ++i) { ExpressionTree child = foldMaybe(expr.getChildren()[i]); if (child.getConstant() == TruthValue.YES_NO_NULL) { switch (expr.getOperator()) { case ExpressionTree.Operator.AND: expr.getChildren().RemoveAt(i); i -= 1; break; case ExpressionTree.Operator.OR: // a maybe will kill the or condition return(child); default: throw new InvalidOperationException("Got a maybe as child of " + expr); } } else { expr.getChildren()[i] = child; } } if (expr.getChildren().Count == 0) { return(new ExpressionTree(TruthValue.YES_NO_NULL)); } } return(expr); }