public static void collectOr(Expr expr, List<ExprList> list) { if (expr instanceof E_LogicalOr) { E_LogicalOr e = (E_LogicalOr) expr; collectOr(e.getArg1(), list); collectOr(e.getArg2(), list); } else if (expr instanceof E_LogicalAnd) { // List<Expr> ors = new ArrayList<Expr>(); ExprList ors = new ExprList(); collectAnd(expr, ors); list.add(ors); } else { list.add(new ExprList(expr)); } }
public static Expr handle(ExprFunction expr) { // System.out.println("Converting to DNF: [" + expr.getClass() + "]: " + expr); // not(and(A, B)) -> or(not A, not B) // not(or(A, B)) -> or(not A, not B) if (expr instanceof E_LogicalNot) { Expr tmp = ((E_LogicalNot) expr).getArg(); if (!(tmp instanceof ExprFunction)) { return expr; } ExprFunction child = (ExprFunction) tmp; Expr newExpr = expr; if (child instanceof E_LogicalAnd) { newExpr = new E_LogicalOr( eval(new E_LogicalNot(child.getArg(1))), eval(new E_LogicalNot(child.getArg(2)))); } else if (child instanceof E_LogicalOr) { newExpr = new E_LogicalAnd( eval(new E_LogicalNot(child.getArg(1))), eval(new E_LogicalNot(child.getArg(2)))); } else if (child instanceof E_LogicalNot) { // Remove double negation newExpr = eval(child.getArg(1)); } else { return expr; } return eval(newExpr); } else if (expr instanceof E_LogicalOr) { // return expr; // return eval(expr); return new E_LogicalOr(eval(expr.getArg(1)), eval(expr.getArg(2))); } /* Given: * (A or B) AND (C x D) becomes: * (A and (C x D)) OR (B and (c x D)) * * * (A or B) AND (C or D) * * Goal: * (A and C) OR (A and D) OR (B and C) OR (B and D) * * This method transforms any "or" children of an AND node. * other nodes are left untouched: * (A or B) AND (c x D) becomes: * (A and (c x D)) OR (B and (c x D)) */ else if (expr instanceof E_LogicalAnd) { Expr aa = eval(expr.getArg(1)); Expr bb = eval(expr.getArg(2)); E_LogicalOr a = null; Expr b = null; if (aa instanceof E_LogicalOr) { a = (E_LogicalOr) aa; b = bb; } else if (bb instanceof E_LogicalOr) { a = (E_LogicalOr) bb; b = aa; } if (a == null) { return new E_LogicalAnd(aa, bb); } else { return new E_LogicalOr( eval(new E_LogicalAnd(a.getArg(1), b)), eval(new E_LogicalAnd(a.getArg(2), b))); } } else if (expr instanceof E_NotEquals) { // Normalize (a != b) to !(a = b) --- this makes it easier to find "a and !a" // cases return new E_LogicalNot(eval(new E_Equals(expr.getArg(1), expr.getArg(2)))); } return expr; /* if(expr instanceof E_LogicalNot) { Expr tmp = ((E_LogicalNot)expr).getArg(); if (!(tmp instanceof ExprFunction)) return expr; ExprFunction child = (ExprFunction) tmp; String newFuncName = ""; if (child.getName().equals("and")) newFuncName = "or"; else if (child.getName().equals("or")) newFuncName = "and"; else if (child.getName().equals("not")) // Remove double negation return eval(child.getChildren().get(0)); else return expr; FuncExpr result = new FuncExpr(newFuncName, child.getArity()); for (int i = 0; i < child.getArity(); ++i) result.setChild(i, new FuncExpr("not", child.getChildren().get(i))); return eval(result); } if (expr.getName().equals("or")) { List<IExpr> children = new ArrayList<IExpr>(); for (IExpr child : expr.getChildren()) children.add(eval(child)); if (!ExprUtil.containsDirectFuncChild(children, "or")) return new FuncExpr("or", children); // flatten or expressions // or(or(A, B), C) becomes or(A, B, C) List<IExpr> resultChildren = new ArrayList<IExpr>(); for (IExpr child : children) if (ExprUtil.isFunc(child, "or")) resultChildren.addAll(child.getChildren()); else resultChildren.add(child); return new FuncExpr("or", resultChildren); } if (expr.getName().equals("and")) { List<IExpr> children = new ArrayList<IExpr>(); for (IExpr child : expr.getChildren()) children.add(eval(child)); // FIXME an and-node must have at least 2 children // but maybe validation should be done somewhere else // On the other hand it might be convenient to assume that // whenever a binary expression only contains a single child // it should be treated as if there was no operation at all. // No 'or'-expression => nothing todo if (!ExprUtil.containsDirectFuncChild(children, "or")) return new FuncExpr("and", children); // Collect all expressions List<List<IExpr>> tables = new ArrayList<List<IExpr>>(); for (IExpr child : children) { if (ExprUtil.isFunc(child, "or")) tables.add(child.getChildren()); else tables.add(Collections.singletonList(child)); } Collection<List<IExpr>> joinedTable = new JoinIterable<IExpr>( tables); FuncExpr result = new FuncExpr("or", joinedTable.size()); // List<IExpr> resultChildren = new ArrayList<IExpr>(); int i = 0; for (List<IExpr> row : joinedTable) { IExpr newChild = new FuncExpr("and", row); result.setChild(i, newChild); ++i; } return result; } // TODO Auto-generated method stub return expr; */ }