220 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			220 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
| /*
 | |
|  * testSudoku.cpp
 | |
|  * @brief develop code for Sudoku CSP solver
 | |
|  * @date Jan 29, 2012
 | |
|  * @author Frank Dellaert
 | |
|  */
 | |
| 
 | |
| #include <gtsam_unstable/discrete/CSP.h>
 | |
| #include <CppUnitLite/TestHarness.h>
 | |
| #include <boost/assign/std/map.hpp>
 | |
| using boost::assign::insert;
 | |
| #include <iostream>
 | |
| #include <sstream>
 | |
| #include <stdarg.h>
 | |
| 
 | |
| using namespace std;
 | |
| using namespace gtsam;
 | |
| 
 | |
| #define PRINT false
 | |
| 
 | |
| class Sudoku: public CSP {
 | |
| 
 | |
|   /// sudoku size
 | |
|   size_t n_;
 | |
| 
 | |
|   /// discrete keys
 | |
|   typedef std::pair<size_t, size_t> IJ;
 | |
|   std::map<IJ, DiscreteKey> 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);
 | |
| }
 | |
| /* ************************************************************************* */
 | |
| 
 |