/* Copyright 2014 Julia s.r.l. This file is part of BeeDeeDee. BeeDeeDee is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. BeeDeeDee is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with BeeDeeDee. If not, see <http://www.gnu.org/licenses/>. */ package com.juliasoft.beedeedee.examples.queens; import com.juliasoft.beedeedee.factories.JavaBDDAdapterFactory; import com.juliasoft.julia.checkers.nullness.Inner0NonNull; import com.juliasoft.julia.checkers.nullness.Inner1NonNull; import com.juliasoft.utils.concurrent.Executors; import net.sf.javabdd.*; /** * @author John Whaley */ public class NQueens { static BDDFactory B; static boolean TRACE; static int N = 10; /* Size of the chess board */ static @Inner0NonNull @Inner1NonNull BDD[][] X; /* BDD variable array */ static BDD queen; /* N-queen problem expressed as a BDD */ static BDD solution; /* One solution */ public static void main(String[] args) { // if (args.length != 1) { // System.err.println("USAGE: java NQueens N"); // return; // } if(args.length > 0) { N = Integer.parseInt(args[0]); } if (N <= 0) { System.err.println("USAGE: java NQueens N"); return; } TRACE = true; long time = System.currentTimeMillis(); runTest(); freeAll(); time = System.currentTimeMillis() - time; System.out.println("Time: "+time/1000.+" seconds"); Executors.shutdown(); // BDDFactory.CacheStats cachestats = B.getCacheStats(); // if (cachestats != null && cachestats.uniqueAccess > 0) { // System.out.println(cachestats); // } // B.done(); // B = null; } private static double runTest() { if (B == null) { /* Initialize with reasonable nodes and cache size and NxN variables */ String numOfNodes = System.getProperty("bddnodes"); int numberOfNodes; if (numOfNodes == null) numberOfNodes = (int) (Math.pow(4.42, N-6))*1000; else numberOfNodes = Integer.parseInt(numOfNodes); String cache = System.getProperty("bddcache"); int cacheSize = cache == null ? 10000 : Integer.parseInt(cache); numberOfNodes = Math.max(10000, numberOfNodes); // B = BDDFactory.init(numberOfNodes, cacheSize); B = JavaBDDAdapterFactory.init(numberOfNodes, cacheSize); } if (B.varNum() < N * N) B.setVarNum(N * N); queen = B.one(); int i, j; /* Build variable array */ X = new BDD[N][N]; for (i = 0; i < N; i++) for (j = 0; j < N; j++) X[i][j] = B.ithVar(i * N + j); /* Place a queen in each row */ for (i = 0; i < N; i++) { BDD e = B.zero(); for (j = 0; j < N; j++) { e.orWith(X[i][j].id()); } queen.andWith(e); } /* Build requirements for each variable(field) */ for (i = 0; i < N; i++) for (j = 0; j < N; j++) { if (TRACE) System.out.print("Adding position " + i + "," + j+" \r"); build(i, j); } solution = queen.satOne(); double result = queen.satCount(); /* Print the results */ if (TRACE) { System.out.println("There are " + (long) result + " solutions."); double result2 = solution.satCount(); System.out.println("Here is "+(long) result2 + " solution:"); solution.printSet(); System.out.println(); } return result; } private static void freeAll() { for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) X[i][j].free(); queen.free(); solution.free(); } private static void build(int i, int j) { BDD a = B.one(), b = B.one(), c = B.one(), d = B.one(); /* No one in the same column */ for (int l = 0; l < N; l++) { if (l != j) { BDD u = X[i][l].apply(X[i][j], BDDFactory.nand); a.andWith(u); } } /* No one in the same row */ for (int k = 0; k < N; k++) { if (k != i) { BDD u = X[i][j].apply(X[k][j], BDDFactory.nand); b.andWith(u); } } /* No one in the same up-right diagonal */ for (int k = 0; k < N; k++) { int ll = k - i + j; if (ll >= 0 && ll < N) { if (k != i) { BDD u = X[i][j].apply(X[k][ll], BDDFactory.nand); c.andWith(u); } } } /* No one in the same down-right diagonal */ for (int k = 0; k < N; k++) { int ll = i + j - k; if (ll >= 0 && ll < N) { if (k != i) { BDD u = X[i][j].apply(X[k][ll], BDDFactory.nand); d.andWith(u); } } } c.andWith(d); b.andWith(c); a.andWith(b); queen.andWith(a); } }