8 #include "inc_solver.h"
9 #include "solver_interface.h"
17 void EqualOneToCNF(vector<int> literals, vector< vector<int> > & cnf){
18 int N = literals.size();
19 cnf.push_back(literals);
22 // this one is a->~b, a->~c, ...
23 for (int j=0; j<N-1; j++){
24 for (int k=j+1; k<N; k++){
25 dnf.push_back(-literals[j]);
26 dnf.push_back(-literals[k]);
33 void LessEqualOneToCNF(vector<int> literals, vector< vector<int> > & cnf){
34 int N = literals.size();
36 // this one is a->~b, a->~c, ...
37 for (int j=0; j<N-1; j++){
38 for (int k=j+1; k<N; k++){
39 dnf.push_back(-literals[j]);
40 dnf.push_back(-literals[k]);
47 bool validateSolution(int N, int *table, int size){
48 for(int k=0; k<size; k++){
52 for (int j= row*N; j<(row+1)*N; j++)
53 if(j!=k && table[j] >0){
56 for(int j=0; j<N; j++){
58 if(indx !=k && table[indx]>0){
67 if(k!=indx && table[indx]>0){
75 if(k!=indx && table[indx]>0){
83 if(k!=indx && table[indx]>0){
91 if(k!=indx && table[indx]>0){
101 void printValidationStatus(int N, int *table, int size){
102 if(validateSolution(N, table, size)){
103 printf("***CORRECT****\n");
105 printf("***WRONG******\n");
110 void printSolution(int N, int *table, int size){
111 for(int i=0; i<size; i++){
124 void originalNqueensEncoding(int N){
127 int ** VarName = new int * [N];
128 for (int i=0; i<N; i++){
129 VarName[i] = new int [N];
130 for (int j=0; j<N; j++){
131 VarName[i][j] = kk++;
136 vector< vector<int> > cnf;
140 // generator formula per row
141 // v1 + v2 + v3 + v4 + ... = 1r
142 for (int i=0; i<N; i++){
143 for (int j=0; j<N; j++){
144 vars.push_back(VarName[i][j]);
146 EqualOneToCNF(vars, cnf);
150 // generator formula per col
151 // v1 + v2 + v3 + v4 + ... = 1r
152 for (int i=0; i<N; i++){
153 for (int j=0; j<N; j++){
154 vars.push_back(VarName[j][i]);
156 EqualOneToCNF(vars, cnf);
161 for (int i=0; i<N-1; i++){
162 for (int j=0; j<N-i; j++){
163 vars.push_back(VarName[j][i+j]);
165 LessEqualOneToCNF(vars, cnf);
168 for (int i=1; i<N-1; i++){
169 for (int j=0; j<N-i; j++){
170 vars.push_back(VarName[j+i][j]);
172 LessEqualOneToCNF(vars, cnf);
175 for (int i=0; i<N-1; i++){
176 for (int j=0; j<N-i; j++){
177 vars.push_back(VarName[j][N-1 - (i+j)]);
179 LessEqualOneToCNF(vars, cnf);
182 for (int i=1; i<N-1; i++){
183 for (int j=0; j<N-i; j++){
184 vars.push_back(VarName[j+i][N-1-j]);
186 LessEqualOneToCNF(vars, cnf);
190 IncrementalSolver *solver =allocIncrementalSolver();
192 for (int i=0; i<cnf.size(); i++){
193 addArrayClauseLiteral(solver, cnf[i].size(), cnf[i].data());
195 finishedClauses(solver);
197 int result = solve(solver);
199 cout << "SAT Solving time: " << (stop_s-start_s)/double(CLOCKS_PER_SEC)*1000 << " ms" << endl;
202 printf("Problem is unsat\n");
205 printSolution(N, &solver->solution[1], solver->solutionsize);
206 printValidationStatus(N, &solver->solution[1], solver->solutionsize);
210 printf("Unknown results from SAT Solver...\n");
213 deleteIncrementalSolver(solver);
217 void csolverNQueensSub(int N){
218 CSolver *solver = new CSolver();
220 for(int i=0; i<N; i++){
223 uint64_t range[2*N-1];
224 for(int i=0; i<2*N-1; i++){
227 Set *domainSet = solver->createSet(1, domain, N);
228 Set *rangeSet = solver->createSet(1, range, 2*N-1);
229 vector<Element *> Xs;
230 vector<Element *> Ys;
231 for(int i=0; i<N; i++){
232 Xs.push_back(solver->getElementVar(domainSet));
233 Ys.push_back(solver->getElementVar(domainSet));
235 Set *d1[] = {domainSet, domainSet};
236 Function *sub = solver->createFunctionOperator(SATC_SUB, rangeSet, SATC_NOOVERFLOW);
237 //X shouldn't be equal
238 for(int i=0; i<N-1; i++){
239 for(int j=i+1; j<N; j++ ){
240 Element *e1x = Xs[i];
241 Element *e2x = Xs[j];
242 Predicate *eq = solver->createPredicateOperator(SATC_EQUALS);
243 Element *inputs2 [] = {e1x, e2x};
244 BooleanEdge equals = solver->applyPredicate(eq, inputs2, 2);
245 solver->addConstraint(solver->applyLogicalOperation(SATC_NOT, equals));
248 //Y shouldn't be equal
249 for(int i=0; i<N-1; i++){
250 for(int j=i+1; j<N; j++ ){
251 Element *e1y = Ys[i];
252 Element *e2y = Ys[j];
253 Predicate *eq = solver->createPredicateOperator(SATC_EQUALS);
254 Element *inputs2 [] = {e1y, e2y};
255 BooleanEdge equals = solver->applyPredicate(eq, inputs2, 2);
256 solver->addConstraint(solver->applyLogicalOperation(SATC_NOT, equals));
259 //vertical difference and horizontal difference shouldn't be equal shouldn't be equal
260 BooleanEdge overflow = solver->getBooleanVar(2);
261 Set *d2[] = {rangeSet, rangeSet};
262 for(int i=0; i<N-1; i++){
263 for(int j=i+1; j<N; j++ ){
264 Element *e1y = Ys[i];
265 Element *e2y = Ys[j];
266 Element *e1x = Xs[i];
267 Element *e2x = Xs[j];
268 Function *f1 = solver->createFunctionOperator(SATC_SUB, rangeSet, SATC_IGNORE);
269 Element *in1[] = {e1x, e2x};
270 Element *subx = solver->applyFunction(f1, in1, 2, overflow);
271 Element *in2[] = {e1y, e2y};
272 Element *suby = solver->applyFunction(f1, in2, 2, overflow);
273 Predicate *eq = solver->createPredicateOperator(SATC_EQUALS);
274 Element *inputs2 [] = {subx, suby};
275 BooleanEdge equals = solver->applyPredicate(eq, inputs2, 2);
276 solver->addConstraint(solver->applyLogicalOperation(SATC_NOT, equals));
280 // solver->serialize();
281 if (solver->solve() != 1){
282 printf("Problem is Unsolvable ...\n");
285 memset( table, 0, N*N*sizeof(int) );
286 for(int i=0; i<N; i++){
287 uint x = solver->getElementValue(Xs[i]);
288 uint y = solver->getElementValue(Ys[i]);
289 // printf("X=%d, Y=%d\n", x, y);
293 printSolution(N, table, N*N);
294 printValidationStatus(N, table, N*N);
299 void atmostOneConstraint(CSolver *solver, vector<BooleanEdge> &constraints){
300 int size = constraints.size();
304 solver->addConstraint(constraints[0]);
306 // solver->addConstraint(solver->applyLogicalOperation(SATC_OR, &constraints[0], size))
307 for(int i=0; i<size-1; i++){
308 for(int j=i+1; j<size; j++){
309 BooleanEdge const1 = solver->applyLogicalOperation(SATC_NOT, constraints[i]);
310 BooleanEdge const2 = solver->applyLogicalOperation(SATC_NOT, constraints[j]);
311 BooleanEdge array[] = {const1, const2};
312 solver->addConstraint( solver->applyLogicalOperation(SATC_OR, (BooleanEdge *)array, 2));
319 void mustHaveValueConstraint(CSolver* solver, vector<Element*> &elems){
320 for(int i=0; i<elems.size(); i++){
321 solver->mustHaveValue(elems[i]);
325 void differentInEachRow(CSolver* solver, int N, vector<Element*> &elems){
326 Predicate *eq = solver->createPredicateOperator(SATC_EQUALS);
327 for(int i=0; i<N-1; i++){
328 for(int j=i+1; j<N; j++ ){
329 Element *e1x = elems[i];
330 Element *e2x = elems[j];
331 Element *inputs2 [] = {e1x, e2x};
332 BooleanEdge equals = solver->applyPredicate(eq, inputs2, 2);
333 solver->addConstraint(solver->applyLogicalOperation(SATC_NOT, equals));
340 void diagonallyDifferentConstraint(CSolver *solver, int N, vector<Element*> &elems){
341 Predicate *eq = solver->createPredicateOperator(SATC_EQUALS);
342 for(int i=N-1; i>0; i--){
343 // cout << "i:" << i << "\t";
344 vector<BooleanEdge> diagonals;
345 for(int j=i; j>=0; j--){
347 Element* e1 = elems[index];
348 // cout << "e" << e1 <<"=" << j << ", ";
349 Element* e2 = solver->getElementConst(2, (uint64_t) j);
350 Element* in[] = {e1, e2};
351 BooleanEdge equals = solver->applyPredicate(eq, in, 2);
352 diagonals.push_back(equals);
356 atmostOneConstraint(solver, diagonals);
358 for(int i=1; i< N-1; i++){
359 // cout << "i:" << i << "\t";
360 vector<BooleanEdge> diagonals;
361 for(int j=i; j<N; j++){
362 int index =N-1- (j-i);
363 Element* e1 = elems[index];
364 // cout << "e" << e1 <<"=" << j << ", ";
365 Element* e2 = solver->getElementConst(2, (uint64_t) j);
366 Element* in[] = {e1, e2};
367 BooleanEdge equals = solver->applyPredicate(eq, in, 2);
368 diagonals.push_back(equals);
372 atmostOneConstraint(solver, diagonals);
378 void diagonallyDifferentConstraintBothDir(CSolver *solver, int N, vector<Element*> &elems){
379 diagonallyDifferentConstraint(solver, N, elems);
380 reverse(elems.begin(), elems.end());
381 // cout << "Other Diagonal:" << endl;
382 diagonallyDifferentConstraint(solver, N, elems);
386 void csolverNQueens(int N){
391 CSolver *solver = new CSolver();
393 for(int i=0; i<N; i++){
396 Set *domainSet = solver->createSet(1, domain, N);
397 vector<Element *> elems;
398 for(int i=0; i<N; i++){
399 elems.push_back(solver->getElementVar(domainSet));
401 mustHaveValueConstraint(solver, elems);
402 differentInEachRow(solver, N, elems);
403 diagonallyDifferentConstraintBothDir(solver, N, elems);
404 // solver->printConstraints();
405 // solver->serialize();
406 if (solver->solve() != 1){
407 printf("Problem is Unsolvable ...\n");
410 memset( table, 0, N*N*sizeof(int) );
411 for(int i=0; i<N; i++){
412 uint x = solver->getElementValue(elems[i]);
413 // printf("X=%d, Y=%d\n", x, i);
417 printSolution(N, table, N*N);
418 printValidationStatus(N, table, N*N);
425 int main(int argc, char * argv[]){
427 printf("Two arguments are needed\n./nqueen <size> [--csolver]\n");
430 int N = atoi(argv[1]);
432 printf("Running the original encoding ...\n");
433 originalNqueensEncoding(N);
434 }else if( strcmp( argv[2], "--csolver") == 0 ){
435 printf("Running the CSolver encoding ...\n");