| |||||||||||||||||
Sudoku (CP and MIP models) Description Playing Sudoku: fill in the 9x9 grid so that every row, every column and every 3x3 box contains the numbers 1-9.
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
Data Files sudoku_graph.mos (!**************************************************************** Mosel example problems ====================== file sudoku_graph.mos ````````````````````` Sudoku puzzle - data read from file. - Drawing SVG graphs - (c) 2020 Fair Isaac Corporation author: S. Heipcke, Aug 2020 *****************************************************************!) model "sudoku (MIP)" uses "mmxprs", "mmsystem", "mmsvg" parameters DATAFILE = "sudokug290705.dat" COMPLETE=true ! Whether to use complete data set end-parameters forward procedure printsolution forward procedure drawboard(ifsol: boolean) declarations XS = {'A','B','C','D','E','F','G','H','I'} N = XS.size YS = 1..9 M = YS.size VALS = 1..9 VALUE: dynamic array(XS,YS) of integer v: array(XS,YS) of mpvar b: array(XS,YS,VALS) of mpvar DummyObj: linctr end-declarations initializations from "Data/"+DATAFILE VALUE end-initializations ! Fix variables to the given values if COMPLETE then forall(x in XS, y in YS | exists(VALUE(x,y))) v(x,y) = VALUE(x,y) else ! Incomplete fixing: ct:=0 forall(ct as counter, x in XS, y in YS | exists(VALUE(x,y))) if ct>1 then v(x,y) = VALUE(x,y); end-if end-if ! Associate binaries with cell variables forall(x in XS, y in YS) do forall(i in VALS) b(x,y,i) is_binary v(x,y) = sum(i in VALS) i*b(x,y,i) sum(i in VALS) b(x,y,i) = 1 end-do starttime:=gettime ! All-different values in rows forall(y in YS, i in VALS) sum(x in XS) b(x,y,i) = 1 ! All-different values in columns forall(x in XS, i in VALS) sum(y in YS) b(x,y,i) = 1 ! All-different values in 3x3 squares forall(k in 0..2, i in VALS) do sum(x in {'A','B','C'}, y in {1+3*k,2+3*k,3+3*k}) b(x,y,i) = 1 sum(x in {'D','E','F'}, y in {1+3*k,2+3*k,3+3*k}) b(x,y,i) = 1 sum(x in {'G','H','I'}, y in {1+3*k,2+3*k,3+3*k}) b(x,y,i) = 1 end-do ! Solve the problem DummyObj:= 0 drawboard(false) setparam("XPRS_verbose", true) ! setparam("XPRS_presolve",false) ! Uncomment to see effect of presolving minimize(XPRS_LPSTOP,DummyObj) drawboard(false) minimize(XPRS_CONT,DummyObj) if getprobstat=XPRS_OPT then printsolution drawboard(true) end-if ! Wait for display window to close svgwaitclose("Close browser window to terminate model execution.") writeln("Total time: ", gettime-starttime) !**************************** Subroutines **************************** ! Solution printing procedure printsolution writeln("Solution:") write(" "); forall(x in XS) write(x," "); writeln forall(y in YS) do write(y, ": ") forall(x in XS) write(v(x,y).sol," ") writeln end-do returned:=true end-procedure ! **** Match Sudoku coordinates conventions (origin in upper left corner) ! **** with SVG conventions (origin in lower left corner) function posy(y: real): real returned:=M+1-y end-function ! **** Drawing status in SVG format **** public procedure drawboard(ifsol: boolean) ! Interrupt loop if window is closed if svgclosing then return; end-if svgerase ! Draw the board svgaddgroup("B", "Board", SVG_BLACK) forall(i in 1..N+1) do svgaddline(i-0.4, 0.6, i-0.4, N+0.6) if (i-1) mod 3 = 0 then svgsetstyle(svggetlastobj, SVG_STROKEWIDTH,3); end-if end-do forall(j in 1..M+1) do svgaddline(0.6, j-0.4, M+0.6, j-0.4) if (j-1) mod 3 = 0 then svgsetstyle(svggetlastobj, SVG_STROKEWIDTH,3); end-if end-do svgaddrectangle(0.6, 0.6, N, M) svgsetstyle(svggetlastobj, SVG_STROKEWIDTH,3) ! Draw the values svgaddgroup("S", if(ifsol, "Solution", if(getparam("XPRS_LPSTATUS")=1, "Integral values in LP solution", "Initial values"))) svgsetstyle(SVG_FONTSIZE,"x-large") svgaddgroup("V", "Values") svgsetstyle(SVG_FONTSIZE,"xx-small") svgsetstyle(SVG_FILL,SVG_WHITE) svgsetstyle(SVG_FILLOPACITY,1) forall(y in YS) do xct:=0 forall(x in XS, xct as counter) if ifsol then svgaddtext("S", xct-0.1,posy(y+0.1), text(v(x,y).sol)) else if exists(VALUE(x,y)) then svgaddtext("S", xct-0.1,posy(y+0.1), text(VALUE(x,y))) elif (or(i in 1..9) b(x,y,i).sol = 1) then svgaddtext("S", xct-0.1,posy(y+0.1), text(v(x,y).sol)) else svgaddrectangle("V",xct-0.4,posy(y+0.4),1,1) svgsetstyle(svggetlastobj,SVG_FILL,SVG_GREY) svgsetstyle(svggetlastobj,SVG_FILLOPACITY,0.25) svgsetstyle(svggetlastobj,SVG_STROKEWIDTH,0) forall(i in 1..9) do xpos:=xct-0.25+((i-1)mod 3)*0.25 ypos:=posy(y-0.25+((i-1) div 3)*0.25) svgaddtext("V", xpos,ypos, text(i)) end-do end-if end-if end-do svgsetgraphviewbox(0,0, N+3, M+3) svgsetgraphscale(35) svgrefresh svgpause ! Pause at every iteration end-procedure end-model | |||||||||||||||||
© Copyright 2023 Fair Isaac Corporation. |