sudoku2formula.cpp
Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <vector>
00003 #include <iostream>
00004 #include <fstream>
00005 #include <string>
00006 
00007 #include "../libcnf/libcnf.h"
00008 
00009 using namespace cnf;
00010 
00011 
00017 #define NONE 100
00018 
00019 
00020 
00028 void oneValuePerCell(
00029         unsigned int i, unsigned int j, // coordinates of the cell
00030         Formula * form) // formula to which the clauses will be added
00031 {
00032         // First, we add \f$\bar{x_ijk} \land \bar{x_ijk'}\f$ for k<k'
00033         for (unsigned int k1=0; k1<8; k1++)
00034                 for (unsigned int k2=k1+1; k2<9; k2++)
00035                 {
00036                         form->newClause();
00037                         form->addLit(0,false,i,j,k1);
00038                         form->addLit(0,false,i,j,k2);
00039                         form->pushClause();
00040                 }
00041         // Second, we add \lor_{k=0,9} x_ijk
00042         form->newClause();
00043         for (unsigned int k1=0; k1<9; k1++)
00044                 form->addLit(0,true,i,j,k1);
00045         form->pushClause();
00046 }
00047 
00048 
00049 
00057 void oneValuePerLine(
00058         unsigned int i, // number of the line
00059         Formula * form) // formula to which the clauses will be added
00060 {
00061         for (unsigned int k=0; k<9; k++)
00062                 for (unsigned int j1=0; j1<8; j1++)
00063                         for (unsigned int j2=j1+1; j2<9; j2++)
00064                         {
00065                                 form->newClause();
00066                                 form->addLit(0,false,i,j1,k);
00067                                 form->addLit(0,false,i,j2,k);
00068                                 form->pushClause();
00069                         }
00070 }
00071 
00079 void oneValuePerColumn(
00080         unsigned int j, // number of the column
00081         Formula * form) // formula to which the clauses will be added
00082 {
00083         for (unsigned int k=0; k<9; k++)
00084                 for (unsigned int i1=0; i1<8; i1++)
00085                         for (unsigned int i2=i1+1; i2<9; i2++)
00086                         {
00087                                 form->newClause();
00088                                 form->addLit(0,false,i1,j,k);
00089                                 form->addLit(0,false,i2,j,k);
00090                                 form->pushClause();
00091                         }
00092 }
00093 
00094 
00102 void oneValuePerSquare(
00103         unsigned int i, // i=0,2 : "line" of the square to consider
00104         unsigned int j, // j=0,2 : "column" of the square to consider
00105         Formula * form) // formula to which the clauses will be added
00106 {
00107         for (unsigned int k=0; k<9; k++)
00108                 for (unsigned int l1=0; l1<8; l1++)
00109                         for (unsigned int l2=l1+1; l2<9; l2++)
00110                         {
00111                                 form->newClause();
00112                                 form->addLit(0,false, i*3+l1/3, j*3+l1%3, k);
00113                                 form->addLit(0,false, i*3+l2/3, j*3+l2%3, k);
00114                                 form->pushClause();
00115                         }
00116 }
00117 
00118 
00126 void grid2restriction(std::vector< std::vector<int> > grid, Formula * form, VariableSet * vars)
00127 {
00128         for (int i=0; i<9; i++)
00129                 for (int j=0; j<9; j++)
00130                 {
00131                         if (grid[i][j] != NONE)
00132                                 for (int k=0; k<9; k++)
00133                                         if (k==grid[i][j]-1)
00134                                         {
00135                                                 form->newClause();
00136                                                 form->addLit(0,true,i,j,k);
00137                                                 form->pushClause();
00138                                         }
00139                 }
00140 }
00141 
00149 std::vector< std::vector<int> > parseGrid(std::istream * input)
00150 {
00151         std::vector< std::vector<int> > grid;
00152         for (unsigned int i=0; i<9; i++)
00153         {
00154                 std::vector<int> line;
00155  //             std::cout<<std::endl;
00156                 for (unsigned int j=0; j<9; j++)
00157                 {
00158                         char n;
00159                         (*input) >> n;
00160                         if ((*input).good())
00161                         {
00162 //                              std::cout << n ;
00163                                 if (n!='-')
00164                                         line.push_back(n-'0');
00165                                 else
00166                                         line.push_back(NONE);
00167                         }
00168                         else
00169                         //if the stream is stopped
00170                         {
00171                                 std::cout<<"error 403: input stream does not contain enough"
00172                                     <<"information !"<<std::endl;
00173                                 exit(403);
00174                         }
00175                 }
00176                 grid.push_back(line);
00177         }
00178         std::cout<<"Finish parsing grid"<<std::endl;
00179         return grid;
00180 }
00181 
00182 
00183 int main(int argc, char ** argv)
00184 {
00185         VariableSet vars(9,9,9);
00186         Formula form(&vars);
00187         // Exactly one value per cell
00188         for (unsigned int i=0; i<9; i++)
00189                 for (unsigned int j=0; j<9; j++)
00190                         oneValuePerCell(i,j,&form);
00191         // Different element on each line
00192         for (unsigned int i=0; i<9; i++)
00193                 oneValuePerLine(i,&form);
00194         // Different element on each column
00195         for (unsigned int j=0; j<9; j++)
00196                 oneValuePerColumn(j,&form);
00197         // Different element in each "big square"
00198         for (unsigned int i=0; i<3; i++)
00199                 for (unsigned int j=0; j<3; j++)
00200                         oneValuePerSquare(i,j,&form);
00201         // Adding the clauses corresponding to fixed variables (i.e, depends
00202         // on the sudoku grid, so it's time to read it).
00203         std::string comment ("CNF formula corresponding to the sudoku");
00204         if (argc==1)
00205         {
00206                 grid2restriction(parseGrid(&std::cin),&form,&vars);
00207                 form.toFile(&std::cout,comment);
00208         }
00209         else
00210         {
00211                 std::string name (argv[1]);
00212                 std::ifstream input(name.c_str());
00213                 std::cout<<"Reading file "<<name<<std::endl;
00214                 grid2restriction(parseGrid(&input),&form,&vars);
00215                 input.close();
00216                 name+=".dimacs";
00217                 std::ofstream output(name.c_str());
00218                 form.toFile(&output,comment);
00219                 std::cout<<std::endl<<"DIMACS file written: "<<name<<std::endl;
00220         }
00221         std::cout<<std::endl;
00222         return 0;
00223 }
 All Files Functions Defines