/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package csp;
import expressions.FuzzyVariableExpression;
import expressions.FuzzyConstantExpression;
import expressions.FuzzyBinaryExpression;
import expressions.FuzzyUnaryExpression;
import expressions.FuzzyExpression;
import static choco.Choco.*;
import choco.cp.model.*;
import choco.cp.solver.*;
import choco.kernel.model.*;
import choco.kernel.model.constraints.Constraint;
import choco.kernel.model.variables.integer.*;
import choco.cp.solver.search.integer.varselector.*;
import choco.cp.solver.search.integer.valselector.*;
import choco.kernel.solver.*;
import choco.kernel.solver.variables.integer.IntDomainVar;
import java.util.*;
import fuzzysat.*;
import operators.*;
import linearProgramming.*;
import lpsolve.*;
/**
*
* @author steven
*/
public class ChocoSolver {
CPModel model;
Map<String, IntegerVariable> varMap;
int numberOfDegrees;
int timeout = -1;
public ChocoSolver(int numberOfDegrees) {
// System.out.println("CHOCO: numberOfDegrees = " + numberOfDegrees);
model = new CPModel();
varMap = new HashMap();
this.numberOfDegrees = numberOfDegrees;
}
public Map<String, Double> getModel() {
Map<String, Double> res = new HashMap();
double factor = 1.0 / ((double) numberOfDegrees);
CPSolver solver = new CPSolver();
solver.read(model);
// System.out.println(solver.model.constraintsToString());
solver.setVarIntSelector(new MostConstrained(solver));
// solver.setValIntSelector(new RandomIntValSelector());
if(timeout>=0){
solver.setTimeLimit(timeout*1000);
}
solver.solve();
// List<Solution> solutions = solver.getSearchStrategy().solutions;
try{
if (solver.isFeasible()) {
// Solution sol = solutions.get(0);
for (String s : varMap.keySet()) {
// System.out.println(s+ ": "+varMap.get(s));
IntDomainVar v = solver.getVar(varMap.get(s));
if(v!=null)
res.put(s, factor * v.getVal());
else
res.put(s,0.0);
}
return res;
}
else{
// System.out.println("CHOCO: problem not feasible");
return null;
}
}
catch(NullPointerException e){
//time-out
return null;
}
}
public Map<String, Double> getMaximizingModel(String varname) {
if (!varMap.containsKey(varname)) {
System.err.println("WARNING: " + varname + " does not occur in problem (getMaximizingModel/ChocoSolver)");
return getModel();
}
Map<String, Double> res = new HashMap();
double factor = 1.0 / ((double) numberOfDegrees);
CPSolver solver = new CPSolver();
solver.read(model);
solver.maximize(solver.getVar(varMap.get(varname)), false);
//solver.setVarIntSelector(new MostConstrained(solver));
//solver.setValIntSelector(new RandomIntValSelector());
if(timeout>=0){
solver.setTimeLimit(timeout*1000);
}
solver.solve();
// List<Solution> solutions = solver.getSearchStrategy().solutions;
try{
if (solver.isFeasible()) {
// Solution sol = solutions.get(0);
for (String s : varMap.keySet())
res.put(s, factor * solver.getVar(varMap.get(s)).getVal());
return res;
}
else
return null;
}
catch(NullPointerException e){
//time-out
return null;
}
}
public void setTimeout(int timeout){
this.timeout = timeout;
}
public void addFiniteVariable(String name, int k) {
if (k == numberOfDegrees)
addIntegerVariable(name, 0, numberOfDegrees);
else if (!varMap.containsKey(name)) {
int[] values = new int[k + 1];
int step = numberOfDegrees / k;
for (int i = 0; i <= k; i++)
values[i] = i * step;
IntegerVariable var = makeIntVar(name, values);
varMap.put(name, var);
}
}
public void addIntegerVariable(String name, int lowerbound, int upperbound) {
if (!varMap.containsKey(name)) {
IntegerVariable var = makeIntVar(name, lowerbound, upperbound);
varMap.put(name, var);
}
}
public void addFuzzyClause(FuzzyClause fc) {
if (fc.numberOfDisjuncts() > 1)
throw new UnsupportedOperationException();
Literal lit0 = fc.getDisjunct(0);
if (lit0 instanceof FuzzyLiteral) {
FuzzyLiteral lit = (FuzzyLiteral) lit0;
int lowerbound = (int) Math.round(lit.getLowerBound() * numberOfDegrees);
int upperbound = (int) Math.round(lit.getUpperBound() * numberOfDegrees);
// System.out.println("lowerbound = " + lowerbound);
// System.out.println("upperbound = " + upperbound);
IntegerExpressionVariable intExp = getExpression(lit.getExpression().normalise());
if (upperbound == lowerbound){
// System.out.println("CHOCO: constraint added: " + intExp+ " = " + upperbound);
model.addConstraint(eq(intExp, upperbound));
}
else {
if (upperbound < numberOfDegrees)
model.addConstraint(leq(intExp, upperbound));
if (lowerbound > 0)
model.addConstraint(geq(intExp, lowerbound));
}
}
else if (lit0 instanceof LinearLiteral){
Constraint cnstr = getConstraint(((LinearLiteral) lit0).getLinearInequality());
// System.out.println("cnstr = " + cnstr.pretty());
model.addConstraint(cnstr);
}
else
throw new UnsupportedOperationException();
}
public Constraint getConstraint(LinearInequality li) {
String[] vars = li.getVariablesArray();
double[] coeff = li.getCoefficientsArray();
IntegerExpressionVariable current = null;
for (int i = 0; i < vars.length; i++) {
if (!varMap.containsKey(vars[i]))
addIntegerVariable(vars[i], 0, numberOfDegrees);
int a = (int) Math.round(coeff[i]);
if (current == null)
current = mult(varMap.get(vars[i]), a);
else
current = plus(current, mult(varMap.get(vars[i]), a));
}
int type = li.getType();
int rhs = (int) Math.round(li.getRHS() * numberOfDegrees);
if (type == LpSolve.LE)
return leq(current, rhs);
else if (type == LpSolve.GE)
return geq(current, rhs);
else if (type == LpSolve.EQ)
return eq(current, rhs);
else
throw new UnsupportedOperationException();
}
public IntegerExpressionVariable getExpression(FuzzyExpression exp) {
if (exp instanceof FuzzyVariableExpression) {
FuzzyVariableExpression varexp = (FuzzyVariableExpression) exp;
String name = varexp.getName();
if (!varMap.containsKey(name))
addIntegerVariable(name, 0, numberOfDegrees);
return varMap.get(name);
}
else if (exp instanceof FuzzyConstantExpression) {
FuzzyConstantExpression cstexp = (FuzzyConstantExpression) exp;
int val = (int) (Math.round(cstexp.getValue() * numberOfDegrees));
return new IntegerConstantVariable(val);
}
else if (exp instanceof FuzzyUnaryExpression) {
FuzzyUnaryExpression unexp = (FuzzyUnaryExpression) exp;
if (unexp.getOperator() instanceof N) {
IntegerExpressionVariable arg = getExpression(unexp.getArgument());
return plus(numberOfDegrees, mult(arg, -1));
}
else if(unexp.getOperator() instanceof NM){
Constraint cnstr = lt(0,getExpression(unexp.getArgument()));
return ifThenElse(cnstr,new IntegerConstantVariable(0),new IntegerConstantVariable(numberOfDegrees));
}
else
throw new UnsupportedOperationException();
}
else if (exp instanceof FuzzyBinaryExpression) {
FuzzyBinaryExpression binexp = (FuzzyBinaryExpression) exp;
if (binexp.getOperator() instanceof TW) {
IntegerExpressionVariable var1 = getExpression(binexp.getArgument1());
IntegerExpressionVariable var2 = getExpression(binexp.getArgument2());
return max(new IntegerConstantVariable(0), plus(var1, plus(var2, -numberOfDegrees)));
}
else if(binexp.getOperator() instanceof SM){
IntegerExpressionVariable var1 = getExpression(binexp.getArgument1());
IntegerExpressionVariable var2 = getExpression(binexp.getArgument2());
return max(var1,var2);
}
else
throw new UnsupportedOperationException();
}
throw new UnsupportedOperationException();
}
public static void main(String[] args) {
FuzzyBinaryExpression exp1 = new FuzzyBinaryExpression(new FuzzyVariableExpression("x"),
new FuzzyVariableExpression("y"), new TW());
FuzzyBinaryExpression exp2 = new FuzzyBinaryExpression(exp1, new FuzzyVariableExpression("z"), new SW());
// FuzzyExpression exp1 = new FuzzyVariableExpression("x");
FuzzyClause fc1 = new FuzzyClause(new FuzzyLiteral(0.7, 0.7, exp1));
FuzzyClause fc2 = new FuzzyClause(new FuzzyLiteral(0.5, 0.9, new FuzzyVariableExpression("y")));
FuzzyClause fc3 = new FuzzyClause(new FuzzyLiteral(0.2, 0.4, new FuzzyVariableExpression("y")));
ChocoSolver solver = new ChocoSolver(10);
solver.addFuzzyClause(fc1);
solver.addFuzzyClause(fc2);
solver.addFuzzyClause(fc3);
System.out.println(solver.model.constraintsToString());
Map<String, Double> model = solver.getModel();
System.out.println(model);
}
}