/* * testSudoku.cpp * @brief develop code for Sudoku CSP solver * @date Jan 29, 2012 * @author Frank Dellaert */ #include #include #include using boost::assign::insert; #include #include #include using namespace std; using namespace gtsam; #define PRINT false class Sudoku : public CSP { /// sudoku size size_t n_; /// discrete keys typedef std::pair IJ; std::map dkeys_; public: /// return DiscreteKey for cell(i,j) const DiscreteKey& dkey(size_t i, size_t j) const { return dkeys_.at(IJ(i, j)); } /// return Key for cell(i,j) Key key(size_t i, size_t j) const { return dkey(i, j).first; } /// Constructor Sudoku(size_t n, ...) : n_(n) { // Create variables, ordering, and unary constraints va_list ap; va_start(ap, n); Key k = 0; for (size_t i = 0; i < n; ++i) { for (size_t j = 0; j < n; ++j, ++k) { // create the key IJ ij(i, j); dkeys_[ij] = DiscreteKey(k, n); // get the unary constraint, if any int value = va_arg(ap, int); // cout << value << " "; if (value != 0) addSingleValue(dkeys_[ij], value - 1); } // cout << endl; } va_end(ap); // add row constraints for (size_t i = 0; i < n; i++) { DiscreteKeys dkeys; for (size_t j = 0; j < n; j++) dkeys += dkey(i, j); addAllDiff(dkeys); } // add col constraints for (size_t j = 0; j < n; j++) { DiscreteKeys dkeys; for (size_t i = 0; i < n; i++) dkeys += dkey(i, j); addAllDiff(dkeys); } // add box constraints size_t N = (size_t)sqrt(double(n)), i0 = 0; for (size_t I = 0; I < N; I++) { size_t j0 = 0; for (size_t J = 0; J < N; J++) { // Box I,J DiscreteKeys dkeys; for (size_t i = i0; i < i0 + N; i++) for (size_t j = j0; j < j0 + N; j++) dkeys += dkey(i, j); addAllDiff(dkeys); j0 += N; } i0 += N; } } /// Print readable form of assignment void printAssignment(DiscreteFactor::sharedValues assignment) const { for (size_t i = 0; i < n_; i++) { for (size_t j = 0; j < n_; j++) { Key k = key(i, j); cout << 1 + assignment->at(k) << " "; } cout << endl; } } /// solve and print solution void printSolution() { DiscreteFactor::sharedValues MPE = optimalAssignment(); printAssignment(MPE); } }; /* ************************************************************************* */ TEST_UNSAFE(Sudoku, small) { Sudoku csp(4, 1, 0, 0, 4, 0, 0, 0, 0, 4, 0, 2, 0, 0, 1, 0, 0); // Do BP csp.runArcConsistency(4, 10, PRINT); // optimize and check CSP::sharedValues solution = csp.optimalAssignment(); CSP::Values expected; insert(expected)(csp.key(0, 0), 0)(csp.key(0, 1), 1)(csp.key(0, 2), 2)( csp.key(0, 3), 3)(csp.key(1, 0), 2)(csp.key(1, 1), 3)(csp.key(1, 2), 0)( csp.key(1, 3), 1)(csp.key(2, 0), 3)(csp.key(2, 1), 2)(csp.key(2, 2), 1)( csp.key(2, 3), 0)(csp.key(3, 0), 1)(csp.key(3, 1), 0)(csp.key(3, 2), 3)( csp.key(3, 3), 2); EXPECT(assert_equal(expected, *solution)); // csp.printAssignment(solution); } /* ************************************************************************* */ TEST_UNSAFE(Sudoku, easy) { Sudoku sudoku(9, 0, 0, 5, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 7, 3, 7, 6, 0, 0, 0, 8, 2, 0, 0, 0, 1, 2, 0, 0, 9, 0, 0, 4, 0, 0, 0, 2, 0, 3, 0, 0, 0, 3, 0, 0, 1, 0, 0, 9, 6, 0, 0, 0, 1, 9, 0, 0, 0, 5, 8, 9, 7, 0, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 3, 0, 7, 0, 0); // Do BP sudoku.runArcConsistency(4, 10, PRINT); // sudoku.printSolution(); // don't do it } /* ************************************************************************* */ TEST_UNSAFE(Sudoku, extreme) { Sudoku sudoku(9, 0, 0, 9, 7, 4, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 9, 0, 0, 0, 0, 0, 7, 0, 0, 0, 2, 4, 0, 0, 6, 4, 0, 1, 0, 5, 9, 0, 0, 9, 8, 0, 0, 0, 3, 0, 0, 0, 0, 0, 8, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 2, 7, 5, 9, 0, 0); // Do BP sudoku.runArcConsistency(9, 10, PRINT); #ifdef METIS VariableIndexOrdered index(sudoku); index.print("index"); ofstream os("/Users/dellaert/src/hmetis-1.5-osx-i686/extreme-dual.txt"); index.outputMetisFormat(os); #endif // sudoku.printSolution(); // don't do it } /* ************************************************************************* */ TEST_UNSAFE(Sudoku, AJC_3star_Feb8_2012) { Sudoku sudoku(9, 9, 5, 0, 0, 0, 6, 0, 0, 0, 0, 8, 4, 0, 7, 0, 0, 0, 0, 6, 2, 0, 5, 0, 0, 4, 0, 0, 0, 0, 0, 2, 9, 0, 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 6, 3, 0, 0, 0, 0, 0, 9, 0, 0, 7, 0, 6, 8, 0, 0, 0, 0, 3, 0, 2, 9, 0, 0, 0, 0, 1, 0, 0, 0, 3, 7); // Do BP sudoku.runArcConsistency(9, 10, PRINT); // sudoku.printSolution(); // don't do it } /* ************************************************************************* */ int main() { TestResult tr; return TestRegistry::runAllTests(tr); } /* ************************************************************************* */