package de.psi.alloy4smt.hysat;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Vector;
import kodkod.engine.satlab.SATAbortedException;
import kodkod.engine.satlab.SATSolver;
public class HysatSolver implements SATSolver {
private int numclauses;
private int numvars;
private int maxlabel;
private StringBuilder cnfbuilder;
private StringBuilder hyexprbuilder;
private List<Hyvar> hyvars;
private File output;
static private class Hyvar {
public final int min;
public final int max;
public final String name;
public Hyvar(String name, int min, int max) {
this.min = min;
this.max = max;
this.name = name;
}
}
public HysatSolver() {
numclauses = 0;
numvars = 0;
maxlabel = 0;
cnfbuilder = new StringBuilder();
hyexprbuilder = new StringBuilder();
hyvars = new Vector<Hyvar>();
output = null;
}
@Override
public int numberOfVariables() {
return numvars;
}
@Override
public int numberOfClauses() {
return numclauses;
}
@Override
public void addVariables(int numVars) {
if (numVars < 0) throw new IllegalArgumentException();
this.numvars += numVars;
}
@Override
public boolean addClause(int[] lits) {
numclauses++;
cnfbuilder.append("\t");
for (int i = 0; i < lits.length; ++i) {
final int l = Math.abs(lits[i]);
maxlabel = l > maxlabel ? l : maxlabel;
if (i > 0) cnfbuilder.append(" or ");
if (lits[i] < 0) cnfbuilder.append("!");
cnfbuilder.append("cnf_");
cnfbuilder.append(l);
}
cnfbuilder.append(";\n");
return true;
}
@Override
public boolean solve() throws SATAbortedException {
try {
output = File.createTempFile("a4smt", ".hy");
FileWriter writer = new FileWriter(output);
writer.write(toHysat());
writer.close();
} catch (IOException e) {
}
return true;
}
@Override
public boolean valueOf(int variable) {
return false;
}
@Override
public void free() {
}
public String toHysat() {
StringBuilder result = new StringBuilder();
result.append("DECL\n");
if (numvars > 0) {
result.append("\t-- Number of input vars: ");
result.append(numvars);
result.append("\n");
}
for (int i = 1; i <= maxlabel; ++i) {
result.append("\tboole cnf_");
result.append(i);
result.append(";\n");
}
for (Hyvar var : hyvars) {
result.append("\tint [");
result.append(var.min);
result.append(", ");
result.append(var.max);
result.append("] ");
result.append(var.name);
result.append(";\n");
}
result.append("EXPR\n");
result.append(cnfbuilder);
result.append(hyexprbuilder);
return result.toString();
}
public void addHysatVariable(String varname, int min, int max) {
hyvars.add(new Hyvar(varname.replace('$', '_'), min, max));
}
public void addHysatExpr(String expr) {
hyexprbuilder.append("\t");
hyexprbuilder.append(expr.replace('$', '_'));
hyexprbuilder.append(";\n");
}
public File getHysatFile() {
return output;
}
}