package warnings;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import parser.ASTadditiveSetExpression;
import parser.ASTandCondition;
import parser.ASTcondition;
import parser.ASTconstantTermList;
import parser.ASTcurlyBrackets;
import parser.ASTfunctionalSymbol;
import parser.ASTmultiplicativeSetExpression;
import parser.ASTorCondition;
import parser.ASTpredSymbol;
import parser.ASTprogramRule;
import parser.ASTsetExpression;
import parser.ASTsortExpression;
import parser.ASTsortExpressionList;
import parser.ASTsortName;
import parser.ASTsymbolicFunction;
import parser.ASTsymbolicTerm;
import parser.ASTterm;
import parser.ASTtermList;
import parser.ASTunaryCondition;
import parser.ASTunarySetExpression;
import parser.ASTvar;
import parser.SimpleNode;
import parser.SparcTranslatorTreeConstants;
import translating.InstanceGenerator;
import utilities.Pair;
/**
* This class if for creation of a formula from an ASP rule The formula will be
* translated to clingcon and checked for satisfability
*
*/
public class RuleReducer {
// mapping from sort names to sort expressions assigned to the sorts
public HashMap<String, ASTsortExpression> sortNameToExpression;
// mapping from predicate names to a list of names of sorts describing
// arguments
public HashMap<String, ArrayList<String>> predicateArgumentSorts;
private Formula currentFormula;
private InstanceGenerator gen;
UniqueNameGenerator uniqueVariables;
public RuleReducer(HashMap<String, ASTsortExpression> sortNameToExpression,
HashMap<String, ArrayList<String>> predicateArgumentSorts,
InstanceGenerator gen) {
this.sortNameToExpression = sortNameToExpression;
this.predicateArgumentSorts = predicateArgumentSorts;
this.gen = gen;
}
public Formula reduceRule(ASTprogramRule rule) {
currentFormula = null;
uniqueVariables = new UniqueNameGenerator();
uniqueVariables.addUsedNames(fetchVariables(rule));
reduceRule((SimpleNode) rule);
return currentFormula;
}
/**
* Recursively search for all non-relational atoms of the form p(t1,...,t_n)
*
* @param n
* -current node of abstract syntax tree built from the rule
*/
private void reduceRule(SimpleNode n) {
if (n.getId() == SparcTranslatorTreeConstants.JJTEXTENDEDNONRELATOM
|| n.getId() == SparcTranslatorTreeConstants.JJTNONRELATOM) {
if (n.jjtGetNumChildren() == 2) {
// if the predicate has arguments (i.e, it is not of zero
// arity).
ASTpredSymbol predicate = (ASTpredSymbol) n.jjtGetChild(0);
ASTtermList termList = (ASTtermList) n.jjtGetChild(1);
ArrayList<String> sorts = predicateArgumentSorts
.get(predicate.image);
for (int i = 0; i < termList.jjtGetNumChildren(); i++) {
ASTterm term = (ASTterm) termList.jjtGetChild(i);
ASTsortExpression expr = sortNameToExpression.get(sorts
.get(i));
Formula F = reduceTerm(term, expr);
if (currentFormula == null) {
currentFormula = F;
} else {
currentFormula = currentFormula.and(F);
}
}
}
}
for (int i = 0; i < n.jjtGetNumChildren(); i++) {
reduceRule((SimpleNode) n.jjtGetChild(i));
}
}
private Formula reduceTerm(ASTterm term, String sortName) {
return reduceTerm(term, sortNameToExpression.get(sortName));
}
private Formula reduceTerm(ASTterm term, ASTsortExpression expr) {
SimpleNode exprChild = (SimpleNode) expr.jjtGetChild(0);
// expr is set expression
if (exprChild.getId() == SparcTranslatorTreeConstants.JJTSETEXPRESSION) {
return reduceTerm(term, (ASTsetExpression) exprChild);
}
// expr is functionalSymbol()
else if (exprChild.getId() == SparcTranslatorTreeConstants.JJTFUNCTIONALSYMBOL) {
return reduceTerm(term, (ASTfunctionalSymbol) exprChild);
}
else {
HashSet<String> sortInstances = gen.generateInstances(expr, true);
Formula result = null;
if (term.isRecord() && term.hasVariables()) {
result = new PrimitiveFormula(false);
for (String termInSort : sortInstances) {
Formula F = matchTerms(term, termInSort);
if (F != null) {
result = result.or(F);
}
}
return result;
} else {
GroundSet set = null;
if (exprChild.getId() == SparcTranslatorTreeConstants.JJTNUMERICRANGE) {
String[] range = exprChild.image.split(" ");
Integer lowest = Integer.parseInt(range[0]);
Integer highest = Integer.parseInt(range[1]);
set = new NumericRangeGroundSet(lowest, highest);
} else {
set = new MaterializedGroundSet(gen.generateInstances(expr,
true));
}
return new PrimitiveFormula(new Term(term), set);
}
}
}
private Formula matchTerms(ASTterm term,String groundTerm) {
if(term.isRecord()) {
Pair<String, ArrayList<String>> groundRecord = StringListUtils
.splitTerm(groundTerm.toString());
if(groundRecord==null) {
return null;
}
ASTsymbolicTerm symTerm = (ASTsymbolicTerm) term.jjtGetChild(0);
ASTsymbolicFunction symFun = (ASTsymbolicFunction) symTerm
.jjtGetChild(0);
ASTtermList termList = (ASTtermList) symTerm.jjtGetChild(1);
String recordName = symFun.image;
if (groundRecord.first.equals(recordName)
&& groundRecord.second.size() == termList
.jjtGetNumChildren()) {
Formula conjFormula = null;
for (int i = 0; i < groundRecord.second.size(); i++) {
ASTterm rTerm = (ASTterm) termList
.jjtGetChild(i);
Formula matching=matchTerms(rTerm,groundRecord.second.get(i));
if(matching==null)
return null;
if (i == 0) {
conjFormula = matching;
} else {
conjFormula = conjFormula.and(matching);
}
}
return conjFormula;
}
else {
return null;
}
}
else {
return new PrimitiveFormula(new Term(
term), new Term(new ASTterm(groundTerm)), Relation.eqasgn );
}
}
private Formula reduceTerm(ASTterm term, ASTfunctionalSymbol expr) {
if (!term.isVariable() && !term.isRecord()) {
return new PrimitiveFormula(false);
}
ASTsortExpressionList list = (ASTsortExpressionList) expr
.jjtGetChild(0);
String recordName = expr.image.substring(0, expr.image.indexOf('('));
ArrayList<String> newVariables = null;
Formula result = null;
ArrayList<ASTterm> terms=new ArrayList<ASTterm>();
if (term.isVariable()) {
newVariables=uniqueVariables.generateNNewNames(list
.jjtGetNumChildren());
result = new PrimitiveFormula(new Term(term), new Term(recordName,
newVariables), Relation.eqasgn);
for(int i=0;i<newVariables.size();i++) {
ASTvar var=new ASTvar(SparcTranslatorTreeConstants.JJTVAR);
var.image=newVariables.get(i);
ASTterm newTerm=new ASTterm(SparcTranslatorTreeConstants.JJTTERM);
newTerm.jjtAddChild(var, 0);
terms.add(newTerm);
}
} else { // term is a record
ASTsymbolicTerm symTerm = (ASTsymbolicTerm) (term.jjtGetChild(0));
ASTsymbolicFunction symFunc = (ASTsymbolicFunction) (symTerm
.jjtGetChild(0));
String symFuncName = symFunc.image.substring(0,
symFunc.image.indexOf('('));
ASTtermList termList = (ASTtermList) symTerm.jjtGetChild(1);
if (!symFuncName.equals(recordName)) {
return new PrimitiveFormula(false);
} else {
for (int i = 0; i < termList.jjtGetNumChildren(); i++) {
terms.add((ASTterm)termList.jjtGetChild(i));
}
}
}
if (expr.jjtGetNumChildren() > 1) {// if condition presents
ASTcondition cond = (ASTcondition) expr.jjtGetChild(1);
Formula reducedCondition = reduceCondition(cond, terms);
if (result == null)
result = reducedCondition;
else {
result = result.and(reducedCondition);
}
}
for (int i = 0; i < list.jjtGetNumChildren(); i++) {
ASTsortName sortName = (ASTsortName) list.jjtGetChild(i);
ASTterm termToPass = null;
if (term.isVariable()) {
ASTvar var = new ASTvar(SparcTranslatorTreeConstants.JJTVAR);
var.image = newVariables.get(i);
ASTterm newTerm = new ASTterm(
SparcTranslatorTreeConstants.JJTTERM);
newTerm.jjtAddChild(var, 0);
termToPass = newTerm;
} else { // term is record
ASTsymbolicTerm symTerm = (ASTsymbolicTerm) (term
.jjtGetChild(0));
ASTtermList termList = (ASTtermList) symTerm.jjtGetChild(1);
if(list.jjtGetNumChildren()!=termList.jjtGetNumChildren()) {
return new PrimitiveFormula(false);
}
termToPass = (ASTterm) termList.jjtGetChild(i);
}
Formula reducedTerm=reduceTerm(termToPass, sortName.image);
if(result==null) {
result=reducedTerm;
}
else {
result = result.and(reducedTerm);
}
}
return result;
}
private Formula reduceCondition(ASTcondition cond,
ArrayList<ASTterm> terms) {
return reduceCondition((ASTorCondition) cond.jjtGetChild(0),
terms);
}
private Formula reduceCondition(ASTorCondition cond,
ArrayList<ASTterm> terms) {
Formula F = null;
for (int i = 0; i < cond.jjtGetNumChildren(); i++) {
Formula reducedAndCondition = reduceCondition(
(ASTandCondition) cond.jjtGetChild(i), terms);
if (i == 0) {
F = reducedAndCondition;
} else {
F = F.or(reducedAndCondition);
}
}
return F;
}
private Formula reduceCondition(ASTandCondition cond,
ArrayList<ASTterm> terms) {
Formula F = null;
for (int i = 0; i < cond.jjtGetNumChildren(); i++) {
Formula reducedUnaryCondition = reduceCondition(
(ASTunaryCondition) cond.jjtGetChild(i), terms);
if (i == 0) {
F = reducedUnaryCondition;
} else {
F = F.and(reducedUnaryCondition);
}
}
return F;
}
private Formula reduceCondition(ASTunaryCondition cond,
ArrayList<ASTterm> terms) {
if(terms.size()<2) {
return new PrimitiveFormula(false);
}
if (cond.jjtGetNumChildren() == 1) {
ASTcondition childCond = (ASTcondition) cond.jjtGetChild(0);
if(cond.image.trim().equals("not(")) {
return reduceCondition(childCond, terms).negate();
} else {
return reduceCondition(childCond, terms);
}
} else {
String[] relationContents = cond.image.split(" ");
int term1Index = Integer.parseInt(relationContents[0]);
int term2Index = Integer.parseInt(relationContents[2]);
String relationStr = relationContents[1];
Relation rel = null;
if (relationStr.equals(">")) {
rel = Relation.greater;
} else if (relationStr.equals(">=")) {
rel = Relation.greatereq;
} else if (relationStr.equals("<")) {
rel = Relation.less;
} else if (relationStr.equals("<=")) {
rel = Relation.lesseq;
} else if (relationStr.equals("!=")) {
rel = Relation.noteq;
} else if (relationStr.equals("==")) {
rel = Relation.eqrel;
} else if (relationStr.equals("=")) {
rel = Relation.eqasgn;
}
return new PrimitiveFormula(new Term(terms.get(term1Index)), new Term(terms.get(term2Index)),
rel);
}
}
private Formula reduceTerm(ASTterm term, ASTsetExpression expr) {
ASTadditiveSetExpression exprChild = (ASTadditiveSetExpression) expr
.jjtGetChild(0);
return reduceTerm(term, exprChild);
}
private Formula reduceTerm(ASTterm term, ASTadditiveSetExpression expr) {
Formula F = reduceTerm(term,
(ASTmultiplicativeSetExpression) expr.jjtGetChild(0));
for (int i = 1; i < expr.jjtGetNumChildren(); i++) {
Formula nextF = reduceTerm(term,
(ASTmultiplicativeSetExpression) expr.jjtGetChild(i));
switch (expr.image.charAt(i)) {
case '+':
F = F.or(nextF);
break;
case '-':
F = F.and(nextF.negate());
break;
}
}
return F;
}
private Formula reduceTerm(ASTterm term, ASTmultiplicativeSetExpression expr) {
Formula F = reduceTerm(term,
(ASTunarySetExpression) expr.jjtGetChild(0));
for (int i = 1; i < expr.jjtGetNumChildren(); i++) {
Formula nextF = reduceTerm(term,
(ASTunarySetExpression) expr.jjtGetChild(i));
F = F.and(nextF);
}
return F;
}
private Formula reduceTerm(ASTterm termNode, ASTunarySetExpression expr) {
SimpleNode child = (SimpleNode) expr.jjtGetChild(0);
switch (child.getId()) {
case SparcTranslatorTreeConstants.JJTSORTNAME:
return reduceTerm(termNode, sortNameToExpression.get(child.image));
case SparcTranslatorTreeConstants.JJTCURLYBRACKETS:
ASTcurlyBrackets curlyBrackets = (ASTcurlyBrackets) child;
ASTconstantTermList termList = (ASTconstantTermList) curlyBrackets
.jjtGetChild(0);
GroundSet gset = new MaterializedGroundSet(gen.generateInstances(
termList, true));
return new PrimitiveFormula(new Term(termNode), gset);
case SparcTranslatorTreeConstants.JJTSETEXPRESSION:
return reduceTerm(termNode, (ASTsetExpression) child);
case SparcTranslatorTreeConstants.JJTFUNCTIONALSYMBOL:
return reduceTerm(termNode, (ASTfunctionalSymbol)child);
default:
return null;
}
}
private HashSet<String> fetchVariables(ASTprogramRule rule) {
HashSet<String> variables = new HashSet<String>();
fetchVariables((SimpleNode) rule, variables);
return variables;
}
private void fetchVariables(SimpleNode n, HashSet<String> fetchedVariables) {
if (n.getId() == SparcTranslatorTreeConstants.JJTVAR) {
fetchedVariables.add(n.toString());
}
for (int i = 0; i < n.jjtGetNumChildren(); i++) {
fetchVariables((SimpleNode) n.jjtGetChild(i), fetchedVariables);
}
}
}