/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package finiteReduction;
import expressions.FuzzyVariableExpression;
import expressions.FuzzyConstantExpression;
import expressions.FuzzyBinaryExpression;
import expressions.FuzzyUnaryExpression;
import expressions.FuzzyExpression;
import java.util.*;
import util.*;
import fuzzysat.*;
import linearProgramming.*;
import lpsolve.*;
import operators.*;
/**
*
* @author steven
*/
public class FuzzyToDLR {
public static List<DisjunctiveLinearInequality> process(FuzzyLiteral lit,long timeout) {
long starttime = System.currentTimeMillis();
List<DisjunctiveLinearInequality> res = new ArrayList();
MaxMinExp e = clauseToMaxMin(lit.getExpression().normalise());
// System.out.println("lit = " + lit);
// System.out.println("e = " + e);
double upperbound = lit.getUpperBound();
double lowerbound = lit.getLowerBound();
if(System.currentTimeMillis()-starttime>timeout)
return res;
if (upperbound < 1) {
List<MaxMinExp> emax = e.normaliseMax(timeout - (System.currentTimeMillis()-starttime));
// System.out.println("emax = " + emax);
if(System.currentTimeMillis()-starttime>timeout)
return res;
for (MaxMinExp me : emax) {
if (me instanceof NodeExp) {
res.add(new DisjunctiveLinearInequality(((NodeExp) me).getLErelation(upperbound)));
}
else if (me instanceof MinExp) {
DisjunctiveLinearInequality dli = new DisjunctiveLinearInequality();
List<MaxMinExp> leaves = ((MinExp) me).args;
for (MaxMinExp leave : leaves) {
if (leave instanceof NodeExp) {
dli.addDisjunct(((NodeExp) leave).getLErelation(upperbound));
}
else
throw new UnsupportedOperationException();
}
res.add(dli);
}
else
throw new UnsupportedOperationException();
}
}
if (lit.getLowerBound() > 0) {
List<MaxMinExp> emin = e.normaliseMin(timeout - (System.currentTimeMillis()-starttime));
// System.out.println("emin = " + emin);
if(System.currentTimeMillis()-starttime>timeout)
return res;
for (MaxMinExp me : emin) {
if (me instanceof NodeExp) {
res.add(new DisjunctiveLinearInequality(((NodeExp) me).getGErelation(lowerbound)));
}
else if (me instanceof MaxExp) {
DisjunctiveLinearInequality dli = new DisjunctiveLinearInequality();
List<MaxMinExp> leaves = ((MaxExp) me).args;
for (MaxMinExp leave : leaves) {
if (leave instanceof NodeExp) {
dli.addDisjunct(((NodeExp) leave).getGErelation(lowerbound));
}
else
throw new UnsupportedOperationException();
}
res.add(dli);
}
else
throw new UnsupportedOperationException();
}
}
return res;
}
public static MaxMinExp clauseToMaxMin(FuzzyExpression fexp) {
if (fexp instanceof FuzzyConstantExpression) {
return new NodeExp(new HashMap(), ((FuzzyConstantExpression) fexp).getValue());
}
else if (fexp instanceof FuzzyVariableExpression) {
Map<String, Integer> m = new HashMap();
m.put(((FuzzyVariableExpression) fexp).getName(), 1);
return new NodeExp(m, 0);
}
else if (fexp instanceof FuzzyUnaryExpression) {
FuzzyUnaryExpression fu = (FuzzyUnaryExpression) fexp;
if (fu.getOperator() instanceof N) {
MaxMinExp arg = clauseToMaxMin(fu.getArgument());
return arg.getComplement();
}
else
throw new UnsupportedOperationException();
}
else if (fexp instanceof FuzzyBinaryExpression) {
FuzzyBinaryExpression fu = (FuzzyBinaryExpression) fexp;
if (fu.getOperator() instanceof TW) {
MaxMinExp arg1 = clauseToMaxMin(fu.getArgument1());
MaxMinExp arg2 = clauseToMaxMin(fu.getArgument2());
MaxMinExp res = arg1.add(arg2);
NodeExp c = new NodeExp(new HashMap(), -1);
MaxMinExp a = res.add(c);
MaxMinExp b = new NodeExp(new HashMap(), 0);
return new MaxExp(a, b);
}
else if (fu.getOperator() instanceof SM) {
MaxMinExp arg1 = clauseToMaxMin(fu.getArgument1());
MaxMinExp arg2 = clauseToMaxMin(fu.getArgument2());
return new MaxExp(arg1, arg2);
}
else
throw new UnsupportedOperationException();
}
else
throw new UnsupportedOperationException();
}
public abstract static class MaxMinExp {
List<MaxMinExp> args;
double upper = -1;
double lower = -1;
public MaxMinExp() {
args = new ArrayList();
}
public List<MaxMinExp> normaliseMax(long timeout) {
// System.out.println("biep");
List<MaxMinExp> res = new ArrayList();
res.add(this);
return res;
}
public List<MaxMinExp> normaliseMin(long timeout) {
List<MaxMinExp> res = new ArrayList();
res.add(this);
return res;
}
public abstract MaxMinExp add(MaxMinExp ne);
public abstract MaxMinExp getComplement();
public abstract double getUpperbound();
public abstract double getLowerbound();
}
public static class NodeExp extends MaxMinExp {
Map<String, Integer> coefficients;
double constant;
public NodeExp(Map<String, Integer> coefficients, double constant) {
this.coefficients = coefficients;
this.constant = constant;
}
public NodeExp(NodeExp copy) {
coefficients = new HashMap();
for (String s : copy.coefficients.keySet())
coefficients.put(s, copy.coefficients.get(s));
constant = copy.constant;
}
public String toString() {
return coefficients + " + " + constant;
}
public MaxMinExp add(MaxMinExp e) {
if (e instanceof NodeExp) {
NodeExp ne = (NodeExp) e;
NodeExp res = new NodeExp(this);
for (String s : ne.coefficients.keySet()) {
if (coefficients.containsKey(s))
res.coefficients.put(s, coefficients.get(s) + ne.coefficients.get(s));
else
res.coefficients.put(s, ne.coefficients.get(s));
}
res.constant += ne.constant;
return res;
}
else {
return e.add(this);
}
}
public MaxMinExp getComplement() {
Map<String, Integer> resCoeff = new HashMap();
for (String s : coefficients.keySet()) {
resCoeff.put(s, -coefficients.get(s));
}
double resConstant = 1 - constant;
return new NodeExp(resCoeff, resConstant);
}
public LinearInequality getLErelation(double rhs) {
String[] names = coefficients.keySet().toArray(new String[0]);
double[] coeffs = new double[names.length];
for (int i = 0; i < names.length; i++)
coeffs[i] = coefficients.get(names[i]);
return new LinearInequality(names, coeffs, LpSolve.LE, rhs - constant);
}
public LinearInequality getGErelation(double rhs) {
String[] names = coefficients.keySet().toArray(new String[0]);
double[] coeffs = new double[names.length];
for (int i = 0; i < names.length; i++)
coeffs[i] = coefficients.get(names[i]);
return new LinearInequality(names, coeffs, LpSolve.GE, rhs - constant);
}
public double getUpperbound() {
if (upper >= 0)
return upper;
double res = constant;
for (String s : coefficients.keySet()) {
Integer c = coefficients.get(s);
if (c > 0)
res += c;
}
upper = res;
// System.out.println("upperbound " + this + " === " + res);
return res;
}
public double getLowerbound() {
if (lower >= 0)
return lower;
double res = constant;
for (String s : coefficients.keySet()) {
Integer c = coefficients.get(s);
if (c < 0)
res += c;
}
lower = res;
return res;
}
}
public static class MaxExp extends MaxMinExp {
public MaxExp(MaxMinExp l1, MaxMinExp l2) {
args = new ArrayList();
args.add(l1);
args.add(l2);
normalise();
upper = Math.max(l1.upper,l2.upper);
lower = Math.max(l1.lower,l2.lower);
}
public MaxExp(List<MaxMinExp> args0) {
args = args0;
normalise();
}
private void normalise() {
for (int i = 0; i < args.size(); i++) {
if (args.get(i) instanceof MaxExp) {
args.addAll(args.get(i).args);
args.remove(i);
i--;
}
}
for (int i = 0; i < args.size(); i++) {
for (int j = i + 1; j < args.size(); j++) {
if(args.get(i).getUpperbound()<= args.get(j).getLowerbound()){
// System.out.println("biep1");
// System.out.println("arg-i" +args.get(i));
// System.out.println("arg-j" +args.get(j));
// System.out.println("arg-i-upper" +args.get(i).getUpperbound());
// System.out.println("arg-j-lower" +args.get(j).getLowerbound());
args.remove(i);
i--;
break;
}
if(args.get(j).getUpperbound()<= args.get(i).getLowerbound()){
args.remove(j);
j--;
}
}
}
}
public List<MaxMinExp> normaliseMax(long timeout) {
long starttime = System.currentTimeMillis();
List<MaxMinExp> res = new ArrayList();
for (MaxMinExp e : args){
if(System.currentTimeMillis()-starttime > timeout)
return res;
res.addAll(e.normaliseMax(timeout-(System.currentTimeMillis()-starttime)));
}
return res;
}
public List<MaxMinExp> normaliseMin(long timeout) {
long starttime = System.currentTimeMillis();
if (args.size() == 0)
return new ArrayList();
List<MaxMinExp> res = new ArrayList();
res.addAll(args.get(0).normaliseMin(timeout-(System.currentTimeMillis()-starttime)));
for (int i = 1; i < args.size(); i++) {
if(System.currentTimeMillis()-starttime > timeout)
return res;
List<MaxMinExp> l = args.get(i).normaliseMin(timeout-(System.currentTimeMillis()-starttime));
List<MaxMinExp> res1 = res;
res = new ArrayList();
for (MaxMinExp e1 : res1) {
for (MaxMinExp e2 : l) {
res.add(new MaxExp(e1, e2));
}
}
}
return res;
}
public String toString() {
StringBuffer res = new StringBuffer("max(");
for (int i = 0; i < args.size() - 1; i++)
res.append(args.get(i).toString() + ",");
res.append(args.get(args.size() - 1) + ")");
return res.toString();
}
public MaxMinExp getComplement() {
List<MaxMinExp> resArgs = new ArrayList();
for (MaxMinExp e : args)
resArgs.add(e.getComplement());
return new MinExp(resArgs);
}
public MaxMinExp add(MaxMinExp e) {
List<MaxMinExp> res = new ArrayList();
for (MaxMinExp a : args) {
res.add(a.add(e));
}
return new MaxExp(res);
}
public double getUpperbound() {
if (upper >= 0)
return upper;
double res = 0;
for (MaxMinExp exp : args) {
res = Math.max(res, exp.getUpperbound());
}
// System.out.println("Upperbound " + this + "===" + res);
upper = res;
return res;
}
public double getLowerbound() {
if (lower >= 0)
return lower;
double res = 0;
for (MaxMinExp exp : args) {
res = Math.max(res, exp.getLowerbound());
}
lower = res;
return res;
}
}
public static class MinExp extends MaxMinExp {
public MinExp(MaxMinExp l1, MaxMinExp l2) {
args = new ArrayList();
args.add(l1);
args.add(l2);
normalise();
upper = Math.min(l1.upper,l2.upper);
lower = Math.min(l1.lower,l2.lower);
}
public MinExp(List<MaxMinExp> args0) {
args = args0;
normalise();
}
private void normalise() {
for (int i = 0; i < args.size(); i++) {
if (args.get(i) instanceof MinExp) {
args.addAll(args.get(i).args);
args.remove(i);
i--;
}
}
for (int i = 0; i < args.size(); i++) {
for (int j = i + 1; j < args.size(); j++) {
if(args.get(i).getLowerbound()>= args.get(j).getUpperbound()){
args.remove(i);
i--;
break;
}
if(args.get(j).getLowerbound()>= args.get(i).getUpperbound()){
args.remove(j);
j--;
}
}
}
}
public List<MaxMinExp> normaliseMax(long timeout) {
long starttime = System.currentTimeMillis();
if (args.size() == 0)
return new ArrayList();
List<MaxMinExp> res = new ArrayList();
res.addAll(args.get(0).normaliseMax(timeout-(System.currentTimeMillis()-starttime)));
for (int i = 1; i < args.size(); i++) {
if(System.currentTimeMillis()-starttime > timeout)
return res;
// System.out.println(" res-voor ="+res);
List<MaxMinExp> l = args.get(i).normaliseMax(timeout-(System.currentTimeMillis()-starttime));
// System.out.println(" l="+res);
List<MaxMinExp> res1 = res;
res = new ArrayList();
for (MaxMinExp e1 : res1) {
for (MaxMinExp e2 : l) {
res.add(new MinExp(e1, e2));
}
}
// System.out.println(" res-na ="+res);
}
return res;
}
public List<MaxMinExp> normaliseMin(long timeout) {
long starttime = System.currentTimeMillis();
List<MaxMinExp> res = new ArrayList();
for (MaxMinExp e : args){
if(System.currentTimeMillis()-starttime > timeout)
return res;
res.addAll(e.normaliseMin(timeout-(System.currentTimeMillis()-starttime)));
}
return res;
}
public String toString() {
StringBuffer res = new StringBuffer("min(");
for (int i = 0; i < args.size() - 1; i++)
res.append(args.get(i).toString() + ",");
res.append(args.get(args.size() - 1) + ")");
return res.toString();
}
public MaxMinExp getComplement() {
List<MaxMinExp> resArgs = new ArrayList();
for (MaxMinExp e : args)
resArgs.add(e.getComplement());
return new MaxExp(resArgs);
}
public MaxMinExp add(MaxMinExp e) {
List<MaxMinExp> res = new ArrayList();
for (MaxMinExp a : args) {
res.add(a.add(e));
}
return new MinExp(res);
}
public double getUpperbound() {
if (upper >= 0)
return upper;
double res = 1;
for (MaxMinExp exp : args) {
res = Math.min(res, exp.getUpperbound());
}
upper = res;
return res;
}
public double getLowerbound() {
if (lower >= 0)
return lower;
double res = 1;
for (MaxMinExp exp : args) {
res = Math.min(res, exp.getLowerbound());
}
lower = res;
return res;
}
}
public static void main(String[] args) {
FuzzyExpression exp = new FuzzyBinaryExpression(new FuzzyBinaryExpression(new FuzzyVariableExpression("a"),
new FuzzyVariableExpression("b"), new SW()),
new FuzzyBinaryExpression(new FuzzyVariableExpression("c"),
new FuzzyVariableExpression("d"), new SW()),
new TW());
FuzzyLiteral lit = new FuzzyLiteral(0.3, 0.7, exp);
List<DisjunctiveLinearInequality> res = process(lit,1000);
for (DisjunctiveLinearInequality dli : res)
System.out.println(dli);
}
}