/* Copyright 2025, Gurobi Optimization, LLC *//* Sudoku example. The Sudoku board is a 9x9 grid, which is further divided into a 3x3 grid of 3x3 grids. Each cell in the grid must take a value from 0 to 9. No two grid cells in the same row, column, or 3x3 subgrid may take the same value. In the MIP formulation, binary variables x[i,j,v] indicate whether cell <i,j> takes value 'v'. The constraints are as follows: 1. Each cell must take exactly one value (sum_v x[i,j,v] = 1) 2. Each value is used exactly once per row (sum_i x[i,j,v] = 1) 3. Each value is used exactly once per column (sum_j x[i,j,v] = 1) 4. Each value is used exactly once per 3x3 subgrid (sum_grid x[i,j,v] = 1) Input datasets for this example can be found in examples/data/sudoku*.*/importcom.gurobi.gurobi.*;importjava.io.*;publicclassSudoku{publicstaticvoidmain(String[]args){intn=9;ints=3;if(args.length<1){System.out.println("Usage: java Sudoku filename");System.exit(1);}try{GRBEnvenv=newGRBEnv();GRBModelmodel=newGRBModel(env);// Create 3-D array of model variablesGRBVar[][][]vars=newGRBVar[n][n][n];for(inti=0;i<n;i++){for(intj=0;j<n;j++){for(intv=0;v<n;v++){Stringst="G_"+String.valueOf(i)+"_"+String.valueOf(j)+"_"+String.valueOf(v);vars[i][j][v]=model.addVar(0.0,1.0,0.0,GRB.BINARY,st);}}}// Add constraintsGRBLinExprexpr;// Each cell must take one valuefor(inti=0;i<n;i++){for(intj=0;j<n;j++){expr=newGRBLinExpr();expr.addTerms(null,vars[i][j]);Stringst="V_"+String.valueOf(i)+"_"+String.valueOf(j);model.addConstr(expr,GRB.EQUAL,1.0,st);}}// Each value appears once per rowfor(inti=0;i<n;i++){for(intv=0;v<n;v++){expr=newGRBLinExpr();for(intj=0;j<n;j++)expr.addTerm(1.0,vars[i][j][v]);Stringst="R_"+String.valueOf(i)+"_"+String.valueOf(v);model.addConstr(expr,GRB.EQUAL,1.0,st);}}// Each value appears once per columnfor(intj=0;j<n;j++){for(intv=0;v<n;v++){expr=newGRBLinExpr();for(inti=0;i<n;i++)expr.addTerm(1.0,vars[i][j][v]);Stringst="C_"+String.valueOf(j)+"_"+String.valueOf(v);model.addConstr(expr,GRB.EQUAL,1.0,st);}}// Each value appears once per sub-gridfor(intv=0;v<n;v++){for(inti0=0;i0<s;i0++){for(intj0=0;j0<s;j0++){expr=newGRBLinExpr();for(inti1=0;i1<s;i1++){for(intj1=0;j1<s;j1++){expr.addTerm(1.0,vars[i0*s+i1][j0*s+j1][v]);}}Stringst="Sub_"+String.valueOf(v)+"_"+String.valueOf(i0)+"_"+String.valueOf(j0);model.addConstr(expr,GRB.EQUAL,1.0,st);}}}// Fix variables associated with pre-specified cellsFilefile=newFile(args[0]);FileInputStreamfis=newFileInputStream(file);byte[]input=newbyte[n];for(inti=0;i<n;i++){fis.read(input);for(intj=0;j<n;j++){intval=(int)input[j]-48-1;// 0-basedif(val>=0)vars[i][j][val].set(GRB.DoubleAttr.LB,1.0);}// read the endline bytefis.read();}// Optimize modelmodel.optimize();// Write model to filemodel.write("sudoku.lp");double[][][]x=model.get(GRB.DoubleAttr.X,vars);System.out.println();for(inti=0;i<n;i++){for(intj=0;j<n;j++){for(intv=0;v<n;v++){if(x[i][j][v]>0.5){System.out.print(v+1);}}}System.out.println();}// Dispose of model and environmentmodel.dispose();env.dispose();}catch(GRBExceptione){System.out.println("Error code: "+e.getErrorCode()+". "+e.getMessage());}catch(IOExceptione){System.out.println("IO Error");}}}