package com.hpctoday.fada;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import com.hpctoday.fada.integersolver.Solver;
import com.hpctoday.fada.integersolver.SolverFactory;
public class LogicalClause {
private static final Logger log = Logger.getLogger(LogicalClause.class.getName());
private List<Inequation> affine_inequations;
private List<Inequation> non_affine_inequations;
private List<LC_RHS_Term> rhs;
private List<String> variables;
private void SetVariables(List<String> __v) {
variables = __v;
}
private void SetAffineInequations(List<Inequation> __ineqs) {
affine_inequations = __ineqs;
}
private void SetNonAffineInequations(List<Inequation> __ineqs) {
non_affine_inequations = __ineqs;
}
private void SetRHS(List<LC_RHS_Term> __i) {
rhs = __i;
}
public LogicalClause(List<String> __var, List<Inequation> __affine, List<Inequation> __non_affine, List<LC_RHS_Term> __lex) {
SetVariables(__var);
SetAffineInequations(__affine);
SetNonAffineInequations(__non_affine);
SetRHS(__lex);
}
public List<String> GetVariables() {
return variables;
}
public List<Inequation> GetAffineInequations() {
return affine_inequations;
}
public List<LC_RHS_Term> GetLexRelations() {
return rhs;
}
public List<Inequation> GetNonAffineInequations() {
return non_affine_inequations;
}
public boolean IsAffine() {
return non_affine_inequations.isEmpty();
}
@Override
public String toString() {
return Print_str();
}
public String Print_str() {
String result = "";
result += "[ for all " + Global.PrintVector(variables) + ",";
result += "na(" + Global.PrintInequations(non_affine_inequations) + "), ";
result += "a(" + Global.PrintInequations(affine_inequations) + ")";
result += " ==> ";
for (LC_RHS_Term it : rhs)
result += "," + it.Print_str();
return result + "]";
}
public LogicalClause Unify(LogicalClause __clause, List<String> __param) {
if (non_affine_inequations.size() > 0 && __clause.non_affine_inequations.size() > 0) {
for (Inequation it : __clause.non_affine_inequations) {
for (int i = 0; i < non_affine_inequations.size(); ++i) {
Inequation itg = non_affine_inequations.get(i);
List<Inequation> valid = new ArrayList<Inequation>();
if (__Unify(itg, variables, it, __clause.variables, __param, valid)) {
log.trace("LogicalClause::Unify ... UNIFICATION RÉUSSIE");
List<Inequation> _non_affine = new ArrayList<Inequation>();
List<Inequation> _affine = new ArrayList<Inequation>();
List<LC_RHS_Term> _lex = new ArrayList<LC_RHS_Term>();
List<String> _var = new ArrayList<String>();
for (int j = 0; j < non_affine_inequations.size(); ++j) {
Inequation iter = non_affine_inequations.get(j);
if (i != j)
_non_affine.add(iter);
}
for (int j = 0; j < __clause.non_affine_inequations.size(); ++j) {
Inequation iter = __clause.non_affine_inequations.get(j);
if (i != j)
_non_affine.add(iter);
}
// _non_affine=MergeInequations(non_affine_inequations,__clause.non_affine_inequations);
if (non_affine_inequations.size() + __clause.non_affine_inequations.size() - 2 != _non_affine.size()) {
StringBuilder cerr = new StringBuilder();
cerr.append("This :").append(Global.PrintInequations(non_affine_inequations)).append(" size ")
.append(non_affine_inequations.size());
cerr.append("\nclause :").append(Global.PrintInequations(__clause.non_affine_inequations)).append(" size ")
.append(__clause.non_affine_inequations.size());
cerr.append("\n Non affine :").append(Global.PrintInequations(_non_affine)).append(" size ")
.append(_non_affine.size());
cerr.append("\n IT :").append(it);
cerr.append("\n Ineq1 :").append(Print_str());
cerr.append("\n Ineq2 :").append(__clause.Print_str());
cerr.append("\nLogicalClause::Unify ... WARNING (unified term not found)[1]");
throw new RuntimeException(cerr.toString());
}
_non_affine = EliminateDoubles(_non_affine, variables, __param);
/*
* vector<Inequation*>::iterator founded=find(_non_affine.begin(),_non_affine.end(),*it); if(founded !=
* _non_affine.end()) _non_affine.erase(founded); else{
* cerr<<"\nThis :"<<PrintInequations(non_affine_inequations);
* cerr<<"\nclause :"<<PrintInequations(__clause.non_affine_inequations);
* cerr<<"\n Non affine :"<<PrintInequations(&_non_affine); cerr<<"\n IT :";(*it).Print();
* cerr<<"\n Ineq1 :";Print(); cerr<<"\n Ineq2 :";__clause.Print();
* cerr<<"\nLogicalClause::Unify ... WARNING (unified term not found)[1]\n"; throw(INAPPROPRIATE_CASE);
* exit(EXIT_FAILURE); }
*
* founded=find(_non_affine.begin(),_non_affine.end(),*itg); if(founded != _non_affine.end())
* _non_affine.erase(founded); else{ cerr<<"\nLogicalClause::Unify ... WARNING (unified term not found)[2]\n";
* throw(INAPPROPRIATE_CASE); exit(EXIT_FAILURE); }
*/
log.trace("APRÉS UNIFICATION ......." + Global.PrintInequations(_non_affine));
_affine = Global.EliminateTrueAndDoubles(Global.MergeInequations(affine_inequations,
__clause.affine_inequations));
/*
* vector<Inequation*>* __negated=new vector<Inequation*>();__negated=NegateInequations(&valid);
*/
_affine = Global.MergeInequations(_affine, valid);
_lex = Global.MergeLC_RHS_Term(rhs, __clause.rhs);
_var = Global.MergeVariables(variables, __clause.variables);
LogicalClause new_clause = new LogicalClause(_var, _affine, _non_affine, _lex);
log.trace("New Clause: " + new_clause);
// new_clause.Print();
return new_clause;
// FIXME : look for all constraints can be unified when unification succeed for a single one.
// TODO : look for all constraints can be unified when unification succeed for a single one.
}
}
}
return null; // unification failed
}
return null; // unification failed
}
public ContextQuast TraduceToQuast(List<List<Inequation>> env, List<String> __param) {
if (IsAffine()) {
// cout<<"\nLogicalClause::TraduceToQuast...............[debug]\n";
// cout<<"\n ENV = "<<PrintInequations(&env);
Solver solver = SolverFactory.createSolver();
solver.set(-1, -1, variables, __param, affine_inequations);
Quast max = solver.Max();
ContextQuast context = Global.TraduceToContextQuast(max, variables, Global.EliminateDoubles(RHS2Inequations()));
// cout<<"\nTraduit direct .......\n"<<context.Print_str("\n");
context = context.Simplify(env, __param);
// cout<<"\nsimplifié .......\n"<<context.Print_str("\n");
if (context.IsLeaf() && context.GetPolyhedrons().isEmpty()) {
//List<List<Inequation>> __true = new ArrayList<List<Inequation>>();
List<List<Inequation>> __false = new ArrayList<List<Inequation>>();
List<Inequation> v = new ArrayList<Inequation>();
v.add(new Inequation(false));
__false.add(v);
return new ContextQuast(new Condition(new Inequation(true)), new ContextQuast(__false), new ContextQuast());
}
return context;
}
return new ContextQuast();
}
public List<List<Inequation>> RHS2Inequations() {
List<List<Inequation>> result = new ArrayList<List<Inequation>>();
for (LC_RHS_Term it : rhs){
result.add(it.ToInequations());
}
return result;
}
public static LogicalClause LoopProperty(List<String> enclosing_loops, String loop_counter, Inequation non_affine_condition) {
List<String> var = new ArrayList<String>(enclosing_loops);
var.add(loop_counter + "1");
var.add(loop_counter + "2");
Map<String, Expression> __map = new HashMap<String, Expression>();
__map.put(loop_counter, new Expression(loop_counter + "2"));
Inequation copy2 = non_affine_condition.SubstituteByExpression(__map);
__map.clear();
__map.put(loop_counter, new Expression(loop_counter + "1"));
Inequation copy1 = non_affine_condition.Negate(true).SubstituteByExpression(__map);
List<Inequation> non_affine = new ArrayList<Inequation>();
List<Inequation> affine = new ArrayList<Inequation>();
affine.add(new Inequation(new Expression(loop_counter + "1"), Inequation.Predicate.FADA_LESS_EQ, new Expression(loop_counter + "2")));
non_affine.add(copy1);
non_affine.add(copy2);
List<LC_RHS_Term> empty = new ArrayList<LC_RHS_Term>();
return new LogicalClause(var, affine, non_affine, empty);
}
public static List<Inequation> EliminateDoubles(List<Inequation> liste, List<String> var, List<String> param) {
List<Inequation> res = new ArrayList<Inequation>();
for (Inequation it : liste) {
String __ineq = it.PrintAll_str(var, param);
boolean found = false;
for (Inequation it2 : res) {
if (__ineq.equals(it2.PrintAll_str(var, param))) {
found = true;
break;
}
}
if (!found)
res.add(it);
}
return res;
}
public static boolean __Unify(Inequation ineq1, List<String> var1, Inequation ineq2, List<String> var2, List<String> param,
List<Inequation> inequations) {
// cout<<"\n__Unify... "<<ineq1.PrintAll_str(var1,param)<<" avec "<<ineq2.PrintAll_str(var2,param);
if (Inequation.Opposite(ineq1.GetPredicate()) != ineq2.GetPredicate()) {
// cout<<"Fail (operateurs non opposés\n";
return false;
}
if (!Equal(ineq1.GetRHS(), var1, ineq2.GetRHS(), var2, param, inequations)) {
// cout<<"Fail 1\n";
return false;
}
if (Equal(ineq1.GetLHS(), var1, ineq2.GetLHS(), var2, param, inequations)) {
// cout<<"(SUCCESSFUL)\n"<<PrintInequations(inequations);
return true;
} else {
// cout<<"Fail 2\n";
return false;
}
}
public static boolean Equal(Expression exp1, List<String> var1, Expression exp2, List<String> var2, List<String> param,
List<Inequation> inequations) {
if (exp1.IsLeaf() && exp2.IsLeaf()) {
if (exp1.IsValue() && exp2.IsValue() && exp1.GetValue() == exp2.GetValue())
return true;
if (exp1.IsValue() && exp2.IsValue() && exp1.GetValue() != exp2.GetValue())
return false;
if (exp1.IsFunction() && exp2.IsFunction() && !exp1.GetFunctionName().equals(exp2.GetFunctionName()))
return false;
if (exp1.IsArray() && exp2.IsArray() && !exp1.GetArrayName().equals(exp2.GetArrayName()))
return false;
if (exp1.IsFunction() && exp2.IsFunction() && exp1.GetFunctionName().equals(exp2.GetFunctionName())) {
for (int i = 0; i < exp1.GetArguments().size() && i < exp2.GetArguments().size(); i++) {
Expression it = exp1.GetArguments().get(i);
Expression it2 = exp2.GetArguments().get(i);
if (!Equal(it, var1, it2, var2, param, inequations))
return false;
}
return true;
}
if (exp1.IsArray() && exp2.IsArray() && exp1.GetArrayName().equals(exp2.GetArrayName())) {
if (exp1.GetReadStmt() != exp2.GetReadStmt())
return false;
if (exp1.GetIteration().size() != exp2.GetIteration().size())
return false;
for (int i = 0; i < exp1.GetIteration().size() && i < exp2.GetIteration().size(); i++) {
Expression it = exp1.GetIteration().get(i);
Expression it2 = exp2.GetIteration().get(i);
if (!Equal(it, var1, it2, var2, param, inequations))
return false;
}
for (int i = 0; i < exp1.GetIndex().size() && i < exp2.GetIndex().size(); i++) {
Expression it = exp1.GetIndex().get(i);
Expression it2 = exp2.GetIndex().get(i);
if (!Equal(it, var1, it2, var2, param, inequations))
return false;
}
return true;
}
if ((exp1.IsValue() && (exp2.IsFunction() || exp2.IsArray())) || (exp2.IsValue() && (exp1.IsFunction() || exp1.IsArray())))
return false;
if (exp1.IsVariable() && var1.contains(exp1.GetVariableName())) {
if (exp2.IsVariable() && var2.contains(exp2.GetVariableName())) {
if (exp1.GetVariableName().equals(exp2.GetVariableName()))
return true;
}
inequations.add(new Inequation(exp1, Inequation.Predicate.FADA_EQ, exp2));
return true;
// FIXME : it's strongly recommended to generate affine inequations only
// TODO : check wether substituted entity is a parameter
}
if (exp2.IsVariable() && var2.contains(exp2.GetVariableName())) {
inequations.add(new Inequation(exp2, Inequation.Predicate.FADA_EQ, exp1));
return true;
// FIXME : it's strongly recommended to generate affine inequations only
// TODO : check wether substituted entity is a parameter
}
if (exp2.IsVariable() && !var2.contains(exp2.GetVariableName()) && exp1.IsVariable() && !var1.contains(exp1.GetVariableName())
&& !exp2.GetVariableName().equals(exp1.GetVariableName()))
return false;
if (exp2.IsVariable() && !var2.contains(exp2.GetVariableName()) && exp1.IsVariable() && !var1.contains(exp1.GetVariableName())
&& exp2.GetVariableName().equals(exp1.GetVariableName())) {
if (exp1.GetReadStmt() != exp2.GetReadStmt())
return false;
if (exp1.GetIteration().size() != exp2.GetIteration().size())
return false;
for (int i = 0; i < exp1.GetIteration().size() && i < exp2.GetIteration().size(); i++) {
Expression it = exp1.GetIteration().get(i);
Expression it2 = exp2.GetIteration().get(i);
if (!Equal(it, var1, it2, var2, param, inequations))
return false;
}
return true;
}
return false;
// cerr<<"\n Equal (Expression1*, var1, Expression2 ....) ... FATAL ERROR(no matching case)\n";
// cerr<<"\nExp1 : "<<exp1.Print_str();
// cerr<<"\nExp2 : "<<exp2.Print_str()<<"\n";
// throw(INAPPROPRIATE_CASE);
// exit(EXIT_FAILURE);
}
if (exp1.IsLeaf() && !exp2.IsLeaf()) {
if (exp1.IsVariable() && var1.contains(exp1.GetVariableName())) {
inequations.add(new Inequation(exp1, Inequation.Predicate.FADA_EQ, exp2));
return true;
// FIXME : it's strongly recommended to generate affine inequations only
// TODO : check wether substituted entity is a parameter
}
return false;
}
if (exp2.IsLeaf() && !exp1.IsLeaf()) {
if (exp2.IsVariable() && var2.contains(exp2.GetVariableName())) {
inequations.add(new Inequation(exp2, Inequation.Predicate.FADA_EQ, exp1));
return true;
// FIXME : it's strongly recommended to generate affine inequations only
// TODO : check wether substituted entity is a parameter
}
return false;
}
if (exp1.GetOperation() == exp2.GetOperation())
if (Equal(exp1.GetRightChild(), var1, exp2.GetLeftChild(), var2, param, inequations))
return Equal(exp1.GetLeftChild(), var1, exp2.GetLeftChild(), var2, param, inequations);
return false;
}
public LogicalClause Copy(){
List<Inequation> affine_inequations = new ArrayList<Inequation>(this.affine_inequations);
List<Inequation> non_affine_inequations = new ArrayList<Inequation>(this.non_affine_inequations);
List<LC_RHS_Term> rhs = new ArrayList<LC_RHS_Term>(this.rhs);
List<String> variables = new ArrayList<String>(this.variables);
return new LogicalClause(variables, affine_inequations, non_affine_inequations, rhs);
}
}