Generic Sudoku Using Randomization

Hi ,
I have the following question


[Q ] Use parameterized class and concept of constraints to solve following 3 Sudoku and print their solution. The class parameter denotes the size of Sudoku (N x N). Here N can be multiple of 2 or 3.

{A]  -  -  -  3 
     -  -  -  1
     1  -  -  -
     2  -  -  - 

[B]  -  4  -  -  -  -
     -  5  6  -  -  -
     5  -  -  3  2  -
     -  2  3  -  -  5
     -  -  -  5  1  -
     -  -  -  -  6  -

[C]  -  9  8  -  -  3  7  -  6
     -  -  2  -  -  -  -  8  -
     -  -  -  -  -  4  1  -  9
     -  -  6  -  -  -  -  -  -
     -  7  -  5  -  9  -  -  -
     -  -  -  -  7  -  -  -  8
     1  6  -  -  -  -  5  -  -
     -  -  -  -  4  -  -  -  -
     -  -  3  -  2  7  -  -  -  


I don’t want to use Unique Constraint as some Older Simulators don’t support them , although a Solution with Unique Constraint would also be appreciated .

Row and Column with Unique Element is something I achieved but the individual Constraint for 2X2 OR 3X2 OR 3X3 box I am confused with

Regards,
AGIS

In reply to Etrx91:

Hi,

you can find the below logic that contains constraints for solving sudoku puzzle with 9 * 9 size. you can use this logic to come with a generic logic for other sizes as well. Please find the below code.



class sudoku;
	rand int unsigned item[9][9];
	int unsigned problem[9][9];     // the problem data (9*9 matrix with 0 in the blank spaces)
	constraint c1{foreach(item[i,j])              
				item[i][j] inside {[1:9]};}
	
	constraint c2{foreach(item[i,j])   // this constraint is for getting unique elements in each row
				foreach(item[,k])
					if(j != k)
						item[i][j] != item[i][k];}
	
	constraint c3{foreach(item[i,j])    // this constraint is for getting unique elements in each column 
				foreach(item[k,])
					if(i != k)
						item[i][j] != item[k][j];}
					
	constraint c4{foreach(item[i,j])    // this constraint is for getting unique elements in each matrix of 3 * 3
				foreach(item[k,l])
					if((i/3 == k/3)&&(j/3 == l/3)&&(i!=k)&&(j!=l))
						item[i][j]!=item[k][l];}
	
	constraint c5{foreach(item[i,j])
				if(problem[i][j] != 0)
					item[i][j] == problem[i][j];}
						
	function int get_solution(int unsigned prob[9][9]);
		problem = prob;
		return this.randomize();
	endfunction
	
	function void print();
		int k,l;
		$display("\n\n");
		for(int i=0; i<9; i++)
			begin
				for(int j=0; j<9; j++)
					begin	
						$write(" %0d", this.item[i][j]);
						l++;
						if(l%3 == 0)
							$write(" ");
					end
				$display("");
				k++;
				if(k%3 == 0)
					$display("");
			end
		$display("\n\n");
	endfunction
endclass


Here is one method using unique. If you do not want to use unique, you can just replace unique with an equivalent constraint.

The solution below is not scalable for other sudoku sizes. A 9x9 size sudoku is assumed.




class sudoku;

parameter ROWS =9;
parameter COLS =9;

//mat is the final sudoku 9X9 matrix
rand int mat[ROWS][COLS];
//trans_mat is the transpose of the final sudoku
rand int trans_mat[COLS][ROWS];
// boxes has 9 rows. Each row has the elements of the 3X3 grid in sudoku
// that have unique numbers
rand int boxes[COLS][ROWS];

constraint sudoku {
    //make the numbers in the 3X3 grid unique
    foreach(boxes[i])
        unique {boxes[i]};
    //This effectively makes the cols in the sudoku unique
    foreach( trans_mat[i]) {
          unique {trans_mat[i]};
    }
    //make the rows in the sudoku unique
    foreach( mat[i]) {
          unique {mat[i]};
    }
    //This is essentially saying that the 3X3 boxes are rows in boxes array
    foreach(mat[i,j]) {
        boxes[(3*(i/3)) + (j/3)][(3*(i%3))+(j%3)] == mat[i][j];
    }
    //Constrain for the numbers to be used in the sudoku
    foreach(mat[i,j]) {
      mat[i][j] >0;
      mat[i][j] <=9; 
    }
    //Constrain for mat and trans_mat to be transpose of each other
    foreach(mat[k,j]) {
      mat[k][j] == trans_mat[j][k];
    }
}

//Display each element of matrix
function string display_elem(int k);
    return($psprintf("%0d",k));
endfunction:display_elem

//Display each row matrix
function string display_row(input int row[COLS]);
    string disp_string;
    foreach(row[i])
    begin
      disp_string = {disp_string, "\t",  display_elem(row[i])};
    end
    return disp_string;
endfunction:display_row

//Display each matrix
function display_mat(ref int mat[ROWS][COLS]);
    foreach(mat[i])
    begin
        $display(display_row(mat[i]));
    end
    $display("=====================================");
endfunction:display_mat
//Display all matrices for debug
function display_all_mats();
    display_sudoku();
    display_mat(trans_mat);
    display_mat(boxes);
endfunction:display_all_mats

function display_sudoku();
    display_mat(mat);
endfunction:display_sudoku
endclass

module sudoku_tb();

   sudoku sudoku_h;
   
initial
begin
    sudoku_h = new();
    sudoku_h.randomize();
    sudoku_h.display_sudoku();
    sudoku_h.randomize();
    sudoku_h.display_sudoku();
end
endmodule



In reply to puttasatish:

@puttasatish: Shouldn’t the “if” condition in your constraint for unique elements in each 3*3 sub-matrix needs to be fixed like below?


constraint c4{foreach(item[i,j]) // this constraint is for getting unique elements in each matrix of 3 * 3
	foreach(item[k,l])
		//if((i/3 == k/3)&&(j/3 == l/3)&&(i!=k)&&(j!=l))
                  if((i/3 == k/3)&&(j/3 == l/3)&& !(i==k && j==l))
			item[i][j]!=item[k][l];}

Thank you!