package splar.core.constraints;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
public class CNFGenerator {
private Map<String,byte[]> clausesMap = null;
private int varIndex;
public CNFGenerator() {
clausesMap = new HashMap<String, byte[]>();
varIndex = -1;
}
public List<CNFClause> generateCNFInstance(List<BooleanVariableInterface> variables, List<CNFClause> clauses, float clauseDensity, int arity) {
clausesMap.clear();
// store intial clauses in the clauses map
if ( clauses != null ) {
for( CNFClause clause : clauses ) {
storeClause(clause, arity);
}
}
varIndex = -1;
List<CNFClause> createdClauses = new LinkedList<CNFClause>();
// number of clauses to create is clause density times number of variables
int numClausesToCreate = (int)(clauseDensity * variables.size())- (clauses == null ? 0 : clauses.size());
// System.out.println("Needs to create " + numClausesToCreate + " clauses");
// System.out.println("Created clauses -------------------------");
for( int i = 0 ; i < numClausesToCreate ; i++ ) {
CNFClause createdClause = createNewClause(variables, arity);
if ( storeClause(createdClause, arity) ) {
createdClauses.add(createdClause);
}
}
return createdClauses;
}
// Pick three distinct variables randomly
private List<BooleanVariableInterface> pickVariables(List<BooleanVariableInterface> variables, int arity) {
List<BooleanVariableInterface> pickedVars = new ArrayList<BooleanVariableInterface>(arity);
Random randomGen = new Random();
int numVars = variables.size();
for( int i = 0 ; i < arity ; i++ ) {
BooleanVariableInterface var = null;
do {
var = variables.get(Math.abs(randomGen.nextInt())%numVars);
} while ( pickedVars.contains(var) );
pickedVars.add(var);
}
return pickedVars;
}
// private List<BooleanVariableInterface> pickVariables(List<BooleanVariableInterface> variables, int arity) {
// List<BooleanVariableInterface> pickedVars = new ArrayList<BooleanVariableInterface>(arity);
// if ( varIndex == -1 ) {
// Collections.shuffle(variables);
// varIndex++;
// }
// int oldVarIndex = varIndex;
// for( int i = 0 ; i < arity ; i++ ) {
// System.out.println(variables.get(varIndex).getID());
// pickedVars.add(variables.get(varIndex));
// varIndex = (varIndex+1)%variables.size();
// }
// if ( varIndex < oldVarIndex ) {
// Collections.shuffle(variables);
// }
// return pickedVars;
// }
// public static List<BooleanVariableInterface> _pickVariables(List<BooleanVariableInterface> variables, int arity) {
//
// Collections.shuffle(variables);
//
// List<BooleanVariableInterface> uncheckedVars = new LinkedList<BooleanVariableInterface>();
// for( BooleanVariableInterface var : variables ) {
// if ( varsMap.get(var.getID()) == null ) {
// uncheckedVars.add( var );
// }
// if ( uncheckedVars.size() == arity ) break;
// }
// int j = 0;
// for( int i = uncheckedVars.size() ; i < arity ; ) {
// if ( !uncheckedVars.contains(variables.get(j)) ) {
// uncheckedVars.add(variables.get(j));
// i++;
// }
// j++;
// }
// if ( uncheckedVars.size() == 0 ) {
// uncheckedVars = variables;
// }
// assert uncheckedVars.size() >= arity;
//
// List<BooleanVariableInterface> pickedVars = new LinkedList<BooleanVariableInterface>();
// for( int i = 0 ; i < arity ; i++ ) {
// pickedVars.add(uncheckedVars.get(i));
// varsMap.put(uncheckedVars.get(i).getID(), true);
// }
//
// return pickedVars;
// }
private CNFClause createNewClause(List<BooleanVariableInterface> variables, int arity ) {
CNFClause newClause = null;
List<BooleanVariableInterface> pickedVariables = pickVariables(variables, arity);
byte existingClauses[] = null;
int pos = -1;
int maxLoop = Math.max(1000,pickedVariables.size());
do {
newClause = new CNFClause();
for( int i = 0 ; i < arity ; i++) {
newClause.addLiteral(new CNFLiteral(pickedVariables.get(i), new Random().nextBoolean()));
}
String key = getClauseKey(newClause);
pos = getClausePos(newClause);
existingClauses = clausesMap.get(key);
}
while( existingClauses != null && existingClauses[pos] != 0 && (maxLoop--) > 0);
return newClause;
}
private boolean storeClause(CNFClause clause, int arity) {
assert clause.getLiterals().size() == arity;
// find clause key and
// find clause position in possible clauses with same variables
String key = getClauseKey(clause);
int pos = getClausePos(clause);
byte existingClauses[] = clausesMap.get(key);
if ( existingClauses == null ) {
existingClauses = new byte[(int)Math.pow(2, arity)];
clausesMap.put(key, existingClauses);
}
// if clause has not been created yet, creates it and returns true
if ( existingClauses[pos] == 0 ) {
existingClauses[pos] = 1;
// System.out.println("Clause: " + clause + " stored at position " + pos);
return true;
}
// clause already exists
return false;
}
private String getClauseKey(CNFClause clause) {
String key = "";
List<CNFLiteral> literals = clause.getLiterals();
Collections.sort(literals, new CNFLiteralComparator());
for( CNFLiteral literal : literals ){
key += literal.getVariable().getID() + "-";
}
return key;
}
private int getClausePos(CNFClause clause) {
int pos = 0;
int power = 1;
List<CNFLiteral> literals = clause.getLiterals();
Collections.sort(literals, new CNFLiteralComparator());
for( CNFLiteral literal : literals ){
pos += (literal.isPositive() ? 0 : 1) * power;
power *= 2;
}
return pos;
}
public String getStats(Set<CNFClause> clauses) {
return getStats(new LinkedList<CNFClause>(clauses));
}
public String getStats(List<CNFClause> clauses) {
Set<CNFLiteral> literals = new LinkedHashSet<CNFLiteral>();
Set<BooleanVariableInterface> variables = new LinkedHashSet<BooleanVariableInterface>();
int arities[] = {0,0,0,0};
for( CNFClause clause : clauses ) {
literals.addAll(clause.getLiterals());
variables.addAll(clause.getVariables());
int index = clause.getLiterals().size()-1;
arities[index < 4 ? index : arities.length-1]++;
}
String stats = "";
stats += "\r\n Total Variables: " + variables.size();
stats += "\r\n Total Literals.: " + literals.size();
stats += "\r\n Total Clauses..: " + clauses.size();
stats += "\r\n Clause density.: " + (1f*clauses.size())/variables.size();
// stats += "\r\n Clause arity...: ";
// stats += "\r\n - 1 ..........: " + arities[0] + " (" + (1.0*arities[0])/clauses.size()*100 + "%)";
// stats += "\r\n - 2 ..........: " + arities[1] + " (" + (1.0*arities[1])/clauses.size()*100 + "%)";;
// stats += "\r\n - 3 ..........: " + arities[2] + " (" + (1.0*arities[2])/clauses.size()*100 + "%)";;
// stats += "\r\n - > 3 ........: " + arities[3] + " (" + (1.0*arities[3])/clauses.size()*100 + "%)";;
return stats;
}
}
//public class CNFGenerator {
//
// private static Map<String,byte[]> clausesMap = new HashMap<String, byte[]>();
//
// public static List<CNFClause> generate3CNFInstance(List<BooleanVariableInterface> variables, List<CNFClause> clauses, float clauseDensity) {
// List<CNFClause> createdClauses = new LinkedList<CNFClause>();
//
//// System.out.println("Existing clauses -------------------------");
//
// // store intial clauses in the clauses map
// if ( clauses != null ) {
// for( CNFClause clause : clauses ) {
// storeClause(clause);
// }
// }
//
// // number of clauses to create is clause density times number of variables
// int numClausesToCreate = (int)(clauseDensity * variables.size())- (clauses == null ? 0 : clauses.size());
//// System.out.println("Needs to create " + numClausesToCreate + " clauses");
//// System.out.println("Created clauses -------------------------");
// for( int i = 0 ; i < numClausesToCreate ; i++ ) {
// CNFClause createdClause = createNewTernaryClause(variables);
// if ( storeClause(createdClause) ) {
// createdClauses.add(createdClause);
// }
// }
//
// return createdClauses;
// }
//
// public static CNFClause createNewTernaryClause(List<BooleanVariableInterface> variables ) {
// CNFClause newClause = null;
// Collections.shuffle(variables);
// byte existingClauses[] = null;
// int pos = -1;
// int maxLoop = Math.max(1000,variables.size());
// do {
// newClause = new CNFClause();
// for( int i = 0 ; i < 3 ; i++) {
// newClause.addLiteral(new CNFLiteral(variables.get(i), new Random().nextBoolean()));
// }
// String key = getClauseKey(newClause);
// pos = getClausePos(newClause);
// existingClauses = clausesMap.get(key);
// }
// while( existingClauses != null && existingClauses[pos] != 0 && (maxLoop--) > 0);
// return newClause;
// }
//
// public static boolean storeClause(CNFClause clause) {
//
// assert clause.getLiterals().size() == 3;
//
// // find clause key and
// // find clause position in possible clauses with same variables
// String key = getClauseKey(clause);
// int pos = getClausePos(clause);
//
// byte existingClauses[] = clausesMap.get(key);
// if ( existingClauses == null ) {
// existingClauses = new byte[8];
// clausesMap.put(key, existingClauses);
// }
//
// // if clause has not been created yet, creates it and returns true
// if ( existingClauses[pos] == 0 ) {
// existingClauses[pos] = 1;
//// System.out.println("Clause: " + clause + " stored at position " + pos);
// return true;
// }
//
// // clause already exists
// return false;
// }
//
// public static String getClauseKey(CNFClause clause) {
// String key = "";
// List<CNFLiteral> literals = clause.getLiterals();
// Collections.sort(literals, new CNFLiteralComparator());
// for( CNFLiteral literal : literals ){
// key += literal.getVariable().getID() + "-";
// }
// return key;
// }
//
// public static int getClausePos(CNFClause clause) {
// int pos = 0;
// int power = 1;
// List<CNFLiteral> literals = clause.getLiterals();
// Collections.sort(literals, new CNFLiteralComparator());
// for( CNFLiteral literal : literals ){
// pos += (literal.isPositive() ? 0 : 1) * power;
// power *= 2;
// }
// return pos;
// }
//
// public static String getStats(Set<CNFClause> clauses) {
//
// Set<CNFLiteral> literals = new LinkedHashSet<CNFLiteral>();
// Set<BooleanVariableInterface> variables = new LinkedHashSet<BooleanVariableInterface>();
//
// int arities[] = new int[4];
// for( CNFClause clause : clauses ) {
// literals.addAll(clause.getLiterals());
// variables.addAll(clause.getVariables());
// int index = clause.getLiterals().size()-1;
// arities[index < 4 ? index : arities.length-1]++;
//
// }
//
// String stats = "";
//
// stats += "\r\n Total Variables: " + variables.size();
// stats += "\r\n Total Literals.: " + literals.size();
// stats += "\r\n Total Clauses..: " + clauses.size();
// stats += "\r\n Clause density.: " + (1f*clauses.size())/variables.size();
// stats += "\r\n Clause arity...: ";
// stats += "\r\n - 1 ..........: " + arities[0] + " (" + (1.0*arities[0])/clauses.size()*100 + "%)";
// stats += "\r\n - 2 ..........: " + arities[1] + " (" + (1.0*arities[1])/clauses.size()*100 + "%)";;
// stats += "\r\n - 3 ..........: " + arities[2] + " (" + (1.0*arities[2])/clauses.size()*100 + "%)";;
// stats += "\r\n - > 3 ........: " + arities[3] + " (" + (1.0*arities[3])/clauses.size()*100 + "%)";;
//
//
// return stats;
// }
//}
//
//
//
//
//
//
//