//TODO:
package warnings;
import java.util.ArrayList;
import java.util.HashSet;
import parser.ASTunaryCondition;
import parser.SparcTranslatorTreeConstants;
import sorts.Condition;
public class Simplify {
public static ArrayList<PrimitiveFormula> run(
ArrayList<PrimitiveFormula> conj, long maxInt) {
boolean[] toRemove = new boolean[conj.size()];
HashSet<String> arithmeticVariables = VariablesUtils.fetchArithmeticVariables(conj);
for (int i = 0; i < conj.size(); i++) {
PrimitiveFormula iFormula = conj.get(i);
if(iFormula.primitiveType==PrimitiveFormulaType.sat) {
toRemove[i]=true;
}
if(iFormula.primitiveType==PrimitiveFormulaType.unsat) {
return null;
}
if (iFormula.primitiveType == PrimitiveFormulaType.membership) {
Term term = (Term) iFormula.operands[0];
GroundSet set = (GroundSet) iFormula.operands[1];
if (term.isGround()) {
boolean contains=set.containsElement(term.toString());
if (contains && !iFormula.negated || !contains && iFormula.negated) {
toRemove[i] = true;
} else {
return null;
}
} else // term is not ground
if (!term.isRecord()) {
// if it is not ground (after calculation of all arithmetic
// terms)
// and it does not contain '(', it is either an arithmetic
// terms with operations and variables, or a variable
// in both cases if all the variables are arithmetic, it is
// arithmetic.
// and the corresponding set must be numeric:
// 1. Check if it is arithmetic,i.e, if all the variables
// are arithmetic:
HashSet<String> vars = term.fetchVariables();
boolean isArithmetic = true;
for (String var : vars) {
if (!arithmeticVariables.contains(var)) {
isArithmetic = false;
}
}
if (isArithmetic && !set.hasNumber() && !iFormula.negated) {
return null;
}
} else// term is a record
{
// if t is a record and set is numeric, return null
if (set.isNumeric() && !iFormula.negated)
return null;
}
} else if (iFormula.primitiveType == PrimitiveFormulaType.relation) {
Term term1 = (Term) iFormula.operands[0];
Term term2 = (Term) iFormula.operands[1];
// if both term1 and term2 are ground terms, check the relation
if (term1.isGround() && term2.isGround()) {
Condition cond = new Condition();
ArrayList<String> arguments = new ArrayList<String>();
arguments.add(term1.toString());
arguments.add(term2.toString());
boolean conditionSatisfied=cond.checkCondition(
createUnaryCondition("0", "1",
iFormula.rel.toString()), arguments);
if (conditionSatisfied && !iFormula.negated ||
!conditionSatisfied && iFormula.negated) {
toRemove[i] = true;
} else {
return null;
}
} else {
// if they are not ground, check their compatibility
if (iFormula.rel != Relation.noteq) {
if (!comparable(term1, term2, iFormula.rel,
arithmeticVariables)) {
return null;
}
}
}
}
}
ArrayList<PrimitiveFormula> simplifiedConj=new ArrayList<PrimitiveFormula>();
for(int i=0;i<conj.size();i++) {
if(!toRemove[i])
simplifiedConj.add(conj.get(i));
}
return simplifiedConj;
}
private static boolean comparable(Term term1, Term term2, Relation rel,
HashSet<String> arithmeticVariables) {
if(rel==Relation.noteq) {
return true;
}
boolean term1IsRecord = term1.toString().indexOf('(') != -1;
boolean term2IsRecord = term2.toString().indexOf('(') != -1;
if (term1IsRecord && term2IsRecord)
return rel == Relation.eqasgn || rel==Relation.eqrel;
if (term1IsRecord ^ term2IsRecord) {
//lets make term1 to be a record
if(term2IsRecord) {
Term buf=term1;
term1=term2;
term2=buf;
}
// the only case when term1 and term2 are comparable is when term2 is a variable
return term2.isVariable();
}
boolean term1IsNumeric=isNumeric(term1, arithmeticVariables);
boolean term2IsNumeric=isNumeric(term2, arithmeticVariables);
// if they are both numeric, or both symbolic, and non of them is a record they are clearly comparable:
if(!(term1IsNumeric ^ term2IsNumeric)) {
return true;
}
// else we need to consider cases when only one of them is numeric, let it always be t2:
//we swap the terms if it is t1
if(term1IsNumeric) {
Term buf=term1;
term1=term2;
term2=buf;
}
//now we know that t2 is numeric. It can be compatible with the symbolic term iff it is a variable!
return term1.isVariable();
}
private static boolean isNumeric(Term term1,
HashSet<String> arithmeticVariables) {
boolean isNumeric = false;
isNumeric |= arithmeticVariables.contains(term1.toString());
isNumeric |= isNumber(term1.toString());
// we are assuming that term1 is not a record
boolean hasAllArithmeticVariables = true;
HashSet<String> variables = term1.fetchVariables();
for (String variable : variables) {
if (!arithmeticVariables.contains(variable)) {
hasAllArithmeticVariables = false;
}
}
isNumeric |= hasAllArithmeticVariables;
return isNumeric;
}
private static boolean isNumber(String s) {
boolean isNumber = true;
for (char c : s.toCharArray()) {
if (!Character.isDigit(c))
isNumber = false;
}
return isNumber;
}
private static ASTunaryCondition createUnaryCondition(String arg1,
String arg2, String rel) {
ASTunaryCondition cond = new ASTunaryCondition(
SparcTranslatorTreeConstants.JJTUNARYCONDITION);
cond.image = arg1 + " " + rel + " " + arg2;
return cond;
}
}