/*
* 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 EnumeratedChocoSolver {
CPModel model;
Map<String, IntegerVariable> varMap;
int defaultBound;
int k;
int totalNumberOfDegrees;
Map<String, Integer> specificBounds;
int timeout;
public EnumeratedChocoSolver(int defaultBound, Map<String, Integer> specificBounds, int k) {
// System.out.println("CHOCO: numberOfDegrees = " + numberOfDegrees);
model = new CPModel();
varMap = new HashMap();
this.defaultBound = defaultBound;
this.specificBounds = specificBounds;
this.k = k;
totalNumberOfDegrees = defaultBound * k;
// System.out.println("specificBounds = " + specificBounds);
// System.out.println("defaultBound = " + defaultBound);
// System.out.println("totalNumberOfDegrees = " + totalNumberOfDegrees);
}
public Map<String, Double> getModel() {
Map<String, Double> res = new HashMap();
double factor = 1.0 / ((double) totalNumberOfDegrees);
CPSolver solver = new CPSolver();
solver.read(model);
// System.out.println(solver.model.constraintsToString());
// solver.setVarIntSelector(new MostConstrained(solver));
//solver.setValIntSelector(new RandomIntValSelector());
if(timeout>=1){
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){
e.printStackTrace();
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) totalNumberOfDegrees);
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>=1){
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 addVariable(String name) {
if (!varMap.containsKey(name)) {
int nrValues = k*(specificBounds.containsKey(name) ? specificBounds.get(name) : defaultBound);
int[] values = new int[nrValues + 1];
int step = totalNumberOfDegrees / nrValues;
for (int i = 0; i <= nrValues; i++)
values[i] = i * step;
IntegerVariable var = makeIntVar(name, values,"cp:enum");
// System.out.println("var = " + var);
// IntegerVariable var = makeIntVar(name, values,"cp:bound");
// System.out.println("values " + name + " = " + Arrays.toString(values));
varMap.put(name, var);
}
// addIntegerVariable(name,0,totalNumberOfDegrees);
}
public void addIntegerVariable(String name, int lowerbound, int upperbound) {
if (!varMap.containsKey(name)) {
IntegerVariable var = makeIntVar(name, lowerbound, upperbound);
// System.out.println("var = " + var);
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() * totalNumberOfDegrees);
int upperbound = (int) Math.round(lit.getUpperBound() * totalNumberOfDegrees);
// 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 < totalNumberOfDegrees)
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]))
addVariable(vars[i]);
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() * totalNumberOfDegrees);
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))
addVariable(name);
return varMap.get(name);
}
else if (exp instanceof FuzzyConstantExpression) {
FuzzyConstantExpression cstexp = (FuzzyConstantExpression) exp;
int val = (int) (Math.round(cstexp.getValue() * totalNumberOfDegrees));
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(totalNumberOfDegrees, mult(arg, -1));
}
else if(unexp.getOperator() instanceof NM){
Constraint cnstr = lt(0,getExpression(unexp.getArgument()));
return ifThenElse(cnstr,new IntegerConstantVariable(0),new IntegerConstantVariable(totalNumberOfDegrees));
}
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, -totalNumberOfDegrees)));
}
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);
}
}