/*********************************************
 * OPL 12.10.0.0 Model
 * Author: Nourredine.Hail
 * Creation Date: Mar 24, 2021 at 1:30:05 PM
 *********************************************/

using CP;
int SquareSize=50; 

//Define the lines
{int} Set_lines=asSet(1..SquareSize); 
//Define the columns
{int} Set_columuns=asSet(1..SquareSize); 

//Define a cell
tuple tup_cell_position
{
  int lineNum;
  int columnNum;
}

tuple tup_cell_position_number
{
  int lineNum;
  int columnNum;
  int number;
}

{tup_cell_position} Set_all_positions={<i,j>| i in Set_lines, j in Set_columuns};
{tup_cell_position_number} Set_given_positions={};

 execute
{
    var DIR="C:\\Users\\firstname.lastname\\Desktop\\CPLEXMODELS\\Sodoku\\"
    var csvFileName="Sodoku50x50StartingNumbers.csv";
    
    //Load the 1st csv file to populate the 1st set (Set_Store_Load_DC_Info_PlanDlv)
    var InFile_Set_given_positions=new IloOplInputFile(DIR+csvFileName);
	while (!InFile_Set_given_positions.eof)
		{
			var str=InFile_Set_given_positions.readline();
			var ar=str.split(",");
			if (ar.length==3)  //number of fields (or columns) in the csv file (or OPL data structure)
			{
				Set_given_positions.add(
				Opl.intValue(ar[0]),
				Opl.intValue(ar[1]),
				Opl.intValue(ar[2])
				);
			}
		}
		writeln(Set_given_positions)
}		

execute {
  		cp.param.FailLimit = 100000;
}

dvar int+ x_sodoku[Set_all_positions] in 1..SquareSize;
dexpr int objective = sum(i in Set_all_positions) x_sodoku[i];

maximize objective;

subject to
{
  //All numbers of the same line must be different
  forall(i in Set_lines)
  allDifferent(all (j in Set_columuns) x_sodoku[<i,j>]) ;
 
   //All numbers of the same column must be different  
  forall(j in Set_columuns)
  allDifferent(all (i in Set_lines) x_sodoku[<i,j>]) ;
  
  //Don't modify the random cells that are already pre-assigned. These variables must take the values predefined in the pre-poscessing step
  forall(c in Set_given_positions) x_sodoku[<c.lineNum,c.columnNum>]==c.number;
};

//Post processing: retrieve the output and save it in a csv file
tuple tup_output
{
  int lineNum;
  int columnNum;
  int value; 
}

{tup_output} Set_tup_output={<c.lineNum,c.columnNum,x_sodoku[c]> | c in Set_all_positions};

execute 
{ 
var DIR="C:\\Users\\firstname.lastname\\Desktop\\CPLEXMODELS\\Sodoku\\"

var csvFileName="Output_Sodoku_50x50.csv";
var ofile=new IloOplOutputFile(DIR+csvFileName);
//Create the Column names
ofile.writeln( "LineNumber",",","ColumnNumber",",","value"); 
//write the output into the cvs file
for(var a in Set_tup_output)
 ofile.writeln(a.lineNum,",",a.columnNum,",",a.value)

}