8 #include "inc_solver.h"
9 #include "solver_interface.h"
16 void EqualOneToCNF(vector<int> literals, vector< vector<int> > & cnf){
17 int N = literals.size();
18 cnf.push_back(literals);
21 // this one is a->~b, a->~c, ...
22 for (int j=0; j<N-1; j++){
23 for (int k=j+1; k<N; k++){
24 dnf.push_back(-literals[j]);
25 dnf.push_back(-literals[k]);
32 void LessEqualOneToCNF(vector<int> literals, vector< vector<int> > & cnf){
33 int N = literals.size();
35 // this one is a->~b, a->~c, ...
36 for (int j=0; j<N-1; j++){
37 for (int k=j+1; k<N; k++){
38 dnf.push_back(-literals[j]);
39 dnf.push_back(-literals[k]);
46 bool validateSolution(int N, int *table, int size){
47 for(int k=0; k<size; k++){
51 for (int j= row*N; j<(row+1)*N; j++)
52 if(j!=k && table[j] >0){
55 for(int j=0; j<N; j++){
57 if(indx !=k && table[indx]>0){
66 if(k!=indx && table[indx]>0){
74 if(k!=indx && table[indx]>0){
82 if(k!=indx && table[indx]>0){
90 if(k!=indx && table[indx]>0){
100 void printValidationStatus(int N, int *table, int size){
101 if(validateSolution(N, table, size)){
102 printf("***CORRECT****\n");
104 printf("***WRONG******\n");
109 void printSolution(int N, int *table, int size){
110 for(int i=0; i<size; i++){
123 void originalNqueensEncoding(int N){
126 int ** VarName = new int * [N];
127 for (int i=0; i<N; i++){
128 VarName[i] = new int [N];
129 for (int j=0; j<N; j++){
130 VarName[i][j] = kk++;
135 vector< vector<int> > cnf;
139 // generator formula per row
140 // v1 + v2 + v3 + v4 + ... = 1r
141 for (int i=0; i<N; i++){
142 for (int j=0; j<N; j++){
143 vars.push_back(VarName[i][j]);
145 EqualOneToCNF(vars, cnf);
149 // generator formula per col
150 // v1 + v2 + v3 + v4 + ... = 1r
151 for (int i=0; i<N; i++){
152 for (int j=0; j<N; j++){
153 vars.push_back(VarName[j][i]);
155 EqualOneToCNF(vars, cnf);
160 for (int i=0; i<N-1; i++){
161 for (int j=0; j<N-i; j++){
162 vars.push_back(VarName[j][i+j]);
164 LessEqualOneToCNF(vars, cnf);
167 for (int i=1; i<N-1; i++){
168 for (int j=0; j<N-i; j++){
169 vars.push_back(VarName[j+i][j]);
171 LessEqualOneToCNF(vars, cnf);
174 for (int i=0; i<N-1; i++){
175 for (int j=0; j<N-i; j++){
176 vars.push_back(VarName[j][N-1 - (i+j)]);
178 LessEqualOneToCNF(vars, cnf);
181 for (int i=1; i<N-1; i++){
182 for (int j=0; j<N-i; j++){
183 vars.push_back(VarName[j+i][N-1-j]);
185 LessEqualOneToCNF(vars, cnf);
189 IncrementalSolver *solver =allocIncrementalSolver();
191 for (int i=0; i<cnf.size(); i++){
192 addArrayClauseLiteral(solver, cnf[i].size(), cnf[i].data());
194 finishedClauses(solver);
195 int result = solve(solver);
198 printf("Problem is unsat\n");
201 printSolution(N, &solver->solution[1], solver->solutionsize);
202 printValidationStatus(N, &solver->solution[1], solver->solutionsize);
206 printf("Unknown results from SAT Solver...\n");
209 deleteIncrementalSolver(solver);
213 void csolverNQueensSub(int N){
214 CSolver *solver = new CSolver();
216 for(int i=0; i<N; i++){
219 uint64_t range[2*N-1];
220 for(int i=0; i<2*N-1; i++){
223 Set *domainSet = solver->createSet(1, domain, N);
224 Set *rangeSet = solver->createSet(1, range, 2*N-1);
225 vector<Element *> Xs;
226 vector<Element *> Ys;
227 for(int i=0; i<N; i++){
228 Xs.push_back(solver->getElementVar(domainSet));
229 Ys.push_back(solver->getElementVar(domainSet));
231 Set *d1[] = {domainSet, domainSet};
232 Function *sub = solver->createFunctionOperator(SATC_SUB, rangeSet, SATC_NOOVERFLOW);
233 //X shouldn't be equal
234 for(int i=0; i<N-1; i++){
235 for(int j=i+1; j<N; j++ ){
236 Element *e1x = Xs[i];
237 Element *e2x = Xs[j];
238 Predicate *eq = solver->createPredicateOperator(SATC_EQUALS);
239 Element *inputs2 [] = {e1x, e2x};
240 BooleanEdge equals = solver->applyPredicate(eq, inputs2, 2);
241 solver->addConstraint(solver->applyLogicalOperation(SATC_NOT, equals));
244 //Y shouldn't be equal
245 for(int i=0; i<N-1; i++){
246 for(int j=i+1; j<N; j++ ){
247 Element *e1y = Ys[i];
248 Element *e2y = Ys[j];
249 Predicate *eq = solver->createPredicateOperator(SATC_EQUALS);
250 Element *inputs2 [] = {e1y, e2y};
251 BooleanEdge equals = solver->applyPredicate(eq, inputs2, 2);
252 solver->addConstraint(solver->applyLogicalOperation(SATC_NOT, equals));
255 //vertical difference and horizontal difference shouldn't be equal shouldn't be equal
256 BooleanEdge overflow = solver->getBooleanVar(2);
257 Set *d2[] = {rangeSet, rangeSet};
258 for(int i=0; i<N-1; i++){
259 for(int j=i+1; j<N; j++ ){
260 Element *e1y = Ys[i];
261 Element *e2y = Ys[j];
262 Element *e1x = Xs[i];
263 Element *e2x = Xs[j];
264 Function *f1 = solver->createFunctionOperator(SATC_SUB, rangeSet, SATC_IGNORE);
265 Element *in1[] = {e1x, e2x};
266 Element *subx = solver->applyFunction(f1, in1, 2, overflow);
267 Element *in2[] = {e1y, e2y};
268 Element *suby = solver->applyFunction(f1, in2, 2, overflow);
269 Predicate *eq = solver->createPredicateOperator(SATC_EQUALS);
270 Element *inputs2 [] = {subx, suby};
271 BooleanEdge equals = solver->applyPredicate(eq, inputs2, 2);
272 solver->addConstraint(solver->applyLogicalOperation(SATC_NOT, equals));
276 // solver->serialize();
277 if (solver->solve() != 1){
278 printf("Problem is Unsolvable ...\n");
281 memset( table, 0, N*N*sizeof(int) );
282 for(int i=0; i<N; i++){
283 uint x = solver->getElementValue(Xs[i]);
284 uint y = solver->getElementValue(Ys[i]);
285 // printf("X=%d, Y=%d\n", x, y);
289 printSolution(N, table, N*N);
290 printValidationStatus(N, table, N*N);
295 void atmostOneConstraint(CSolver *solver, vector<BooleanEdge> &constraints){
296 int size = constraints.size();
300 solver->addConstraint(constraints[0]);
302 // solver->addConstraint(solver->applyLogicalOperation(SATC_OR, &constraints[0], size))
303 for(int i=0; i<size-1; i++){
304 for(int j=i+1; j<size; j++){
305 BooleanEdge const1 = solver->applyLogicalOperation(SATC_NOT, constraints[i]);
306 BooleanEdge const2 = solver->applyLogicalOperation(SATC_NOT, constraints[j]);
307 BooleanEdge array[] = {const1, const2};
308 solver->addConstraint( solver->applyLogicalOperation(SATC_OR, (BooleanEdge *)array, 2));
315 void mustHaveValueConstraint(CSolver* solver, vector<Element*> &elems){
316 for(int i=0; i<elems.size(); i++){
317 solver->mustHaveValue(elems[i]);
321 void differentInEachRow(CSolver* solver, int N, vector<Element*> &elems){
322 Predicate *eq = solver->createPredicateOperator(SATC_EQUALS);
323 for(int i=0; i<N-1; i++){
324 for(int j=i+1; j<N; j++ ){
325 Element *e1x = elems[i];
326 Element *e2x = elems[j];
327 Element *inputs2 [] = {e1x, e2x};
328 BooleanEdge equals = solver->applyPredicate(eq, inputs2, 2);
329 solver->addConstraint(solver->applyLogicalOperation(SATC_NOT, equals));
336 void diagonallyDifferentConstraint(CSolver *solver, int N, vector<Element*> &elems){
337 Predicate *eq = solver->createPredicateOperator(SATC_EQUALS);
338 for(int i=N-1; i>0; i--){
339 // cout << "i:" << i << "\t";
340 vector<BooleanEdge> diagonals;
341 for(int j=i; j>=0; j--){
343 Element* e1 = elems[index];
344 // cout << "e" << e1 <<"=" << j << ", ";
345 Element* e2 = solver->getElementConst(2, (uint64_t) j);
346 Element* in[] = {e1, e2};
347 BooleanEdge equals = solver->applyPredicate(eq, in, 2);
348 diagonals.push_back(equals);
352 atmostOneConstraint(solver, diagonals);
354 for(int i=1; i< N-1; i++){
355 // cout << "i:" << i << "\t";
356 vector<BooleanEdge> diagonals;
357 for(int j=i; j<N; j++){
358 int index =N-1- (j-i);
359 Element* e1 = elems[index];
360 // cout << "e" << e1 <<"=" << j << ", ";
361 Element* e2 = solver->getElementConst(2, (uint64_t) j);
362 Element* in[] = {e1, e2};
363 BooleanEdge equals = solver->applyPredicate(eq, in, 2);
364 diagonals.push_back(equals);
368 atmostOneConstraint(solver, diagonals);
374 void diagonallyDifferentConstraintBothDir(CSolver *solver, int N, vector<Element*> &elems){
375 diagonallyDifferentConstraint(solver, N, elems);
376 reverse(elems.begin(), elems.end());
377 // cout << "Other Diagonal:" << endl;
378 diagonallyDifferentConstraint(solver, N, elems);
382 void csolverNQueens(int N){
387 CSolver *solver = new CSolver();
389 for(int i=0; i<N; i++){
392 Set *domainSet = solver->createSet(1, domain, N);
393 vector<Element *> elems;
394 for(int i=0; i<N; i++){
395 elems.push_back(solver->getElementVar(domainSet));
397 mustHaveValueConstraint(solver, elems);
398 differentInEachRow(solver, N, elems);
399 diagonallyDifferentConstraintBothDir(solver, N, elems);
400 // solver->printConstraints();
401 // solver->serialize();
402 if (solver->solve() != 1){
403 printf("Problem is Unsolvable ...\n");
406 memset( table, 0, N*N*sizeof(int) );
407 for(int i=0; i<N; i++){
408 uint x = solver->getElementValue(elems[i]);
409 // printf("X=%d, Y=%d\n", x, i);
413 printSolution(N, table, N*N);
414 printValidationStatus(N, table, N*N);
421 int main(int argc, char * argv[]){
423 printf("Two arguments are needed\n./nqueen <size> [--csolver]\n");
426 int N = atoi(argv[1]);
428 printf("Running the original encoding ...\n");
429 originalNqueensEncoding(N);
430 }else if( strcmp( argv[2], "--csolver") == 0 ){
431 printf("Running the CSolver encoding ...\n");