how to update axes in guide - matlab - matlab

i write a code using GUI and Mfile in MATHLAB. in my program i have a board.each time, computer put a marble and rotate the board then get a marble place and rotate direction of the board from user and After each of these things, i want it shows the result in axes1 in GUI. but it doesen't work in line 9 in the code below:
% some codes...
1. while(currentDepth < 7)
2. if(mod(currentDepth,2) ~= (plrC-1))
3. plat(currentDepth);
4. drawTable(); % show the result in axes1 --> it works
5. else
6. getMarble();
7. drawTable(); % show the result in axes1 --> it works
8. rotate();
9. drawTable(); % show the result in axes1 --> it dosen't work
10. end
11. end
% some codes...
.
function drawTable()
global board;
% some codes...
imshow(board,[0 4]);
end
do you have any idea?
it's rotate function. th board is divided into 4 parts just 1 part rotates.
function rotate()
global board;
block = 0;
vector = 'non';
while(block<1 || block>4)
block = str2double(cell2mat(inputdlg('chose a block: 1/2/3/4','board rotation')));
end
switch block
case 1
k=1; z=1;
case 2
k=1; z=4;
case 3
k=4; z=1;
case 4
k=4; z=4;
end
while(~strcmp(vector,'left') && ~strcmp(vector,'right'))
vector = questdlg('rotate left or right','Rotation','left','right','right');
end
if(strcmp(vector,'left'))
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2));
else
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2),3);
end
end
ok now here we have a simplified code. make a new GUI with an axes then run the code below from 'OpeningFnc'. you will see my problem.
function test()
currentDepth = 1;
plrC = 1;
plrO = 2;
board = zeros(6);
while(currentDepth < 40)
if(mod(currentDepth,2) == 1)
plat();
drawTable(); % show the result in axes1 --> it works
else
getMarble();
drawTable(); % show the result in axes1 --> it works
rotate();
drawTable(); % show the result in axes1 --> it dosen't work
end
currentDepth = currentDepth +1;
end
function plat()
for a=1:5000
for b=1:5000
for c=1:50
m = a + b;
end
end
end
row = 1;
column = 1;
while(board(row,column) ~= 0)
row = randi(6);
column = randi(6);
end
board(row,column) = plrC;
row = randi([1 4]);
column = randi([1 4]);
board(row:row+2,column:column+2)=rot90(board(row:row+2,column:column+2));
end
function drawTable()
board(board==0) = board(board==0)+4;
B = zeros(305);
B(:,152:154) = 3;
B(152:154,:) = 3;
for i=1:6
for j=1:6
x = (i*5)+1+(i-1)*45;
y = (j*5)+1+(j-1)*45;
B(x:x+44,y:y+44) = board(i,j);
end
end
imshow(B,[0 4]);
board(board==4) = board(board==4)*0;
end
function getMarble()
board(board==0) = board(board==0)+4;
b = zeros(305);
b(:,152:154) = 3;
b(152:154,:) = 3;
for i=1:6
for j=1:6
x = (i*5)+1+(i-1)*45;
y = (j*5)+1+(j-1)*45;
b(x:x+44,y:y+44) = board(i,j);
end
end
imshow(b,[0 4]);
i = 0;
while(i~=4)
[x,y] = ginput(1);
if(x<0 || x>305 || y<0 || y>305)
i = 0;
else
i = b(ceil(y),ceil(x));
end
end
y = ceil(y/50);
x = ceil(x/50);
board(y,x) = plrO;
end
function rotate()
block = 0;
vector = 'non';
while(block<1 || block>4)
block = str2double(cell2mat(inputdlg('chose a block: 1/2/3/4','board rotation')));
end
switch block
case 1
k=1; z=1;
case 2
k=1; z=4;
case 3
k=4; z=1;
case 4
k=4; z=4;
end
while(~strcmp(vector,'left') && ~strcmp(vector,'right'))
vector = questdlg('rotate left or right','Rotation','left','right','right');
end
if(strcmp(vector,'left'))
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2));
else
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2),3);
end
end
end

as ThP said, i have to add drawnow() function at the end of drawTable.

Related

Use a variable outside the function in matlab

I've written the following function:
% This function plots the contours of likelihood values on the scatter plot of a 2 dimensional data.
function [xgrid,ygrid,Z,xy_matrix] = biVariateContourPlotsGMMCopula(givenData,gmmObject,~,numMeshPoints,x_dim,y_dim)
%INPUT: givenData (MxN, M=number of points, N=Dimension)
% : plo = binary variable (1 plot contour plot, 0 do not plot)
%OUTPUT: xgrid,ygrid,Z ( Z contains the likelihood values of the points defined by xgrid and ygrid)
%load general_info;
d = 2;
if nargin < 5
x_dim = 1;
y_dim = 2;
end
if x_dim == y_dim
hist(givenData(:,x_dim),10);
return;
end
numMeshPoints = min(numMeshPoints,256);
givenData = givenData(:,[x_dim y_dim]);
alpha = gmmObject.alpha;
mu = gmmObject.mu(:,[x_dim y_dim]);
sigma = gmmObject.sigma([x_dim y_dim],[x_dim y_dim],:) + 0.005*repmat(eye(d),[1 1 numel(alpha)]);
gmmObject = gmdistribution(mu,sigma,alpha);
bin_num = 256;
for j = 1:2
l_limit = min(gmmObject.mu(:,j))-3*(max(gmmObject.Sigma(j,j,:))^0.5);
u_limit = max(gmmObject.mu(:,j))+3*(max(gmmObject.Sigma(j,j,:))^0.5);
xmesh_inverse_space{j} = (l_limit:(u_limit-l_limit)/(bin_num-1):u_limit);
end
%if isempty(xmesh)||isempty(pdensity)||isempty(cdensity)
% Following for loop does the non-parameteric estimation of marginal % densities if not provided
for i = 1:d
currentVar = givenData(:,i);
[~,pdensity{i},xmesh{i}]=kde(currentVar,numMeshPoints);
pdensity{i}(pdensity{i}<0) = 0;
cdensity{i} = cumsum(pdensity{i});
cdensity{i} = (cdensity{i}-min(cdensity{i}))/(max(cdensity{i})-min(cdensity{i})); % scaling the cdensity value to be between [0 1]
end
[xgrid,ygrid] = meshgrid(xmesh{1}(2:end-1),xmesh{2}(2:end-1));
for k = 1:d
marginalLogLikelihood_grid{k} = log(pdensity{k}(2:end-1)+eps);
marginalCDFValues_grid{k} = cdensity{k}(2:end-1);
end
[marg1,marg2] = meshgrid(marginalLogLikelihood_grid{1},marginalLogLikelihood_grid{2});
[xg,yg] = meshgrid(marginalCDFValues_grid{1},marginalCDFValues_grid{2});
inputMatrix = [reshape(xg,numel(xg),1) reshape(yg,numel(yg),1)];
clear xg yg;
copulaLogLikelihoodVals = gmmCopulaPDF(inputMatrix,gmmObject,xmesh_inverse_space);
Z = reshape(copulaLogLikelihoodVals,size(marg1,1),size(marg1,2));
Z = Z+marg1+marg2;
Z = exp(Z);
% Getting the likelihood value from the log-likelihood
plot(givenData(:,1),givenData(:,2),'b.','MarkerSize',5);hold
[~,h] = contour(xgrid,ygrid,Z,[4e-6,4e-6]);
% Extract the (x, y) coordinates of the contour and concatenate them along the first dimension
xy_matrix = [];
for i = 1:length(h)
xy = get(h(i), 'XData');
x = xy(1, :);
y = xy(2, :);
xy_matrix = [xy_matrix, [x; y]];
end
% Print the concatenated matrix
disp(xy_matrix);
%title_string = ['GMCM fit (Log-Likelihood = ',num2str(logLikelihoodVal), ')'];
%title(title_string,'FontSize',12,'FontWeight','demi');
axis tight
however xy_matrix is not shown on the workspace.
How do I return the variable xy_matrix so that I can use it in another function?
Function call is inside a for loop as in below:
for i = 1:d
for j = 1:d
subplot(d,d,count); count = count+1;
[xgrid,ygrid,Z,xy_matrix] = biVariateContourPlotsGMMCopula(power_curve_reference_build_T2,gmcObject_bestfit,0,256,i,j);
end
end
So, when I'm including xy_matrix as a params in the function call, it generates the following error:
Have I missed anything here?
When you're calling the function with i==j==1 as parameters x_dim and y_dim, the function ends in the following if:
if x_dim == y_dim
hist(givenData(:,x_dim),10);
return;
end
The return values aren't defined at that point. If you define them in the beginning of the function, you won't get the error message.
function [xgrid,ygrid,Z,xy_matrix] = biVariateContourPlotsGMMCopula(givenData,gmmObject,~,numMeshPoints,x_dim,y_dim)
%INPUT: givenData (MxN, M=number of points, N=Dimension)
% : plo = binary variable (1 plot contour plot, 0 do not plot)
%OUTPUT: xgrid,ygrid,Z ( Z contains the likelihood values of the points defined by xgrid and ygrid)
%load general_info;
xgrid=0;
ygrid=0;
Z=0;
xy_matrix=0;
d = 2;
if nargin < 5
x_dim = 1;
y_dim = 2;
end
Below is a suggestion of some changes of your function call. The return values are saved in cells so that you don't overwrite them in the next iteration. The function is also not called when i==j==x_dim==y_dim.
xgrids={};
ygrids={};
Zs={};
xy_matrices={};
for i = 1:d
for j = 1:d
if i~=j
subplot(d,d,count); count = count+1;
[xgrids{i,j},ygrids{i,j},Zs{i,j},xy_matrices{i,j}] = biVariateContourPlotsGMMCopula(power_curve_reference_build_T2,gmcObject_bestfit,0,256,i,j);
end
end
end

Implementing finding alghoritm with for loops and fmincon function

I am trying to implement this alghoritm for finding a new constraint:
In my case we take only 3 natural numbers i.e 1,2, 3.
The sets associated with those natural numbers are M1, M2 and M3. Instead of the Newton Method in II(2), I chose a solver provided by Matlab fmincon.
Here is my code that is not working!
function[s_new]= checking2(M1,M2,M3,x)
M1=linspace(0,1,10)';
M2=linspace(0,1,100)';
M3=linspace(0,1,1000)';
bool1=0;
eta = 10^-8;
pocz=[];
max=-100;
x = [0.1,0.1]'; % warunek początkowy
A = [];
b = [];
Aeq = [];
beq = [];
Set=[0,1];
g = #(x,s) 5*x(1).^2.*sin(pi.*sqrt(s))./(1+s.^2) - x(2);
g_new = #(s) -g(x,s);
for i=1:length(M1)
if g(x,M1(i,:))>eta
s_new=M1(i,:);
bool1=1;
end
end
if ~bool1
for i=1:length(M1)
if g(x,M1(i,:))>max
pocz=M1(i,:);
max=g(x,M1(i,:));
end
end
if max<-eta
bool1=1;
end
end
if ~bool1
s_maybe = fmincon(g_new,pocz,A,b,Aeq,beq,min(Set),max(Set));
if g(x,s_maybe)>eta
s_new=s_maybe;
bool1=1;
end
end
if ~bool1
for i=1:length(M2)
if g(x,M2(i,:))>eta
s_new=M2(i,:);
bool1=1;
end
end
end
if ~bool1
for i=1:length(M2)
if g(x,M2(i,:))>max
pocz=M2(i,:);
max=g(x,M2(i,:));
end
end
if max<-eta
bool1=1;
end
end
if ~bool1
s_maybe = fmincon(g_new,pocz,A,b,Aeq,beq,min(Set),max(Set));
if g(x,s_maybe)>eta
s_new=s_maybe;
bool1=1;
end
end
if ~bool1
for i=1:length(M3)
if g(x,M3(i,:))>eta
s_new=M3(i,:);
bool1=1;
end
end
end
if ~bool1
s_new = 1;
end
disp(s_new);
The problem is:
Undefined function or variable 's_new'.
Error in checking2 (line 70)
disp(s_new);
So basically everything might be wrong, but I suppose it is something with fmincon.
EDIT:
The purpose of the alghoritm is to find a minimum of an objective function f(x), satisfying all the constraints g(x,s)<=0 for all s in S, where S is an infinite set (some interval in our case).
What my alghoritm does, at first it takes some finite subset of S and calculates the minimum of f on this set, then I am trying to update S with some s_new. This alghoritm that I am trying to implement is exactly the procedure for creating s_new. Then if it works properly, I will add s_new to my subset and calculate the minimum on the new set, and so on until g(x,s)<=eta, where eta is a small number.
I rewrite the algorithm, read through the comments
clc
clear
lb = 0;
ub = 1;
% Given
l = 3;
M1=linspace(lb,ub,10)';
M2=linspace(lb,ub,100)';
M3=linspace(lb,ub,1000)';
% one boolean value for each Matrix
bool = zeros(1,3);
eta = 10^-8;
% Used as fmincon initial starting guess
pocz = nan;
% Used to store the new finding s that fits all the conditions
s_new = nan;
% Fixed x
x = [0.1,0]';
% fmincon linear constraints
A = [];
b = [];
Aeq = [];
beq = [];
% Main function
g = #(x,s) 5*x(1).^2*sin(pi*sqrt(s))/(1+s.^2) - x(2);
% Optimization concerns s only, don't include x as x is fixed
g_new = #(s) -g(x,s);
% Assuming the maximum is reached at the upper bound, used in(II)(2)
max_s = ub;
maxfun = g(x, max_s);
% Use a cell, for each iteration use a specific matrix M
M = {M1, M2, M3};
for j = 1: length(M)
% used in (II)(1)
check = 0;
step = 1;
% (I) step 1
for i = 1:length(M{j})
% Stopping criteria
if g(x, M{j}(i)) > eta
s_new = M{j}(i);
bool(j) = 1;
break;
else
% Function maximum value for next step (II)
if maxfun < g(x, M{j}(i))
maxfun = g(x, M{j}(i));
% To be used in fmincon as pocz
max_s = M{j}(i);
end
end
% To be used in (II)(1)
if maxfun < -eta
check = 1;
end
end
% End of (I)
% Put (II)(1) here step 2
if ~bool(j) && check
step = step + 1;
% Stopping criteria
if step >= l
disp('S_new not defined');
break;
end
% otherwise go to the next M
end
% (II)(2) step 3
if ~bool(j)
step = step + 1;
if maxfun >= -eta && maxfun <= eta
pocz = max_s;
bool(j) = 1;
end
end
%% EDIT: if bool(j) changed to if ~bool(j)
% (II)(2) Continue
if ~bool(j)
s_maybe = fmincon(g_new,pocz,A,b,Aeq,beq,lb,ub);
% End of (II)(2)
% (II)(2)-1 step 4
step = step + 1;
if g(x, s_maybe) > eta
s_new = s_maybe;
bool(j) = 1;
end
% End of (II)(2)-1
end
% Put (II)(2) here step 5
if ~bool(j)
step = step + 1;
% Stopping criteria
if step >= l
disp('S_new not defined');
break;
end
% otherwise go to the next M
end
end

Overlay line plot with shaded bar areas in matlab

I want to overlay my line plot in Matlab with colored bars for different x-axis values. The functionality I'm looking for is much like recessionplot(), but it should not indicate NBER recessions, but user defined periods. I'm able to do this with the following code, but the color of my original line is changed. How do I avoid this in the best way?
%%%%%%%%%%%% Functions to shade %%%%%%%%%%%%%%%%%%%
function []=shadedates(Start,Finish,colorstr)
curax=axis;
indx1=find(Finish>curax(1)); % First Date to include;
indx2=find(Start<curax(2)); % Last Date to include;
indx1=indx1(1);
indx2=indx2(length(indx2));
if Start(indx1)<curax(1);
Start(indx1)=curax(1);
end;
if Finish(indx2)>curax(2);
Finish(indx2)=curax(2);
end;
shade(Start(indx1:indx2),Finish(indx1:indx2),colorstr);
end
function []=shade(Start,Finish,colorstr)
% Start and Finish are Nx1 vectors of starting and ending years.
% The function shades between the start and finish pairs using colorstr
if ~exist('colorstr','var'); colorstr='y'; end; % default is yellow
curax=axis;
y=[curax(3) curax(4) curax(4) curax(3)];
hold on;
for i=1:length(Start);
x=[Start(i) Start(i) Finish(i) Finish(i)];
h=fill(x,y,colorstr);
set(h,'facealpha',.3)
end;
h = findobj(gca,'Type','patch');
set(h,'EdgeColor','none');
% This last one makes the tick marks visible
set(gca, 'Layer', 'top')
end
%%%%%%%%%%%%%%% Create data %%%%%%%%%%%%%%%%%%%%%%
GLI.Dates = transpose(714890:(714890+99));
GLI.GLI = cumsum([50;normrnd(0,1,99,1)]);
GLI.ProsStart = zeros(size(GLI.GLI));
GLI.RecStart = zeros(size(GLI.GLI));
GLI.ProsFin = zeros(size(GLI.GLI));
GLI.RecFin = zeros(size(GLI.GLI));
TempLag = GLI.GLI(1);
CurPhase = 0;
for i=2:size(GLI.GLI,1)
Temp = GLI.GLI(i);
if Temp > TempLag && CurPhase ~= 1
GLI.ProsStart(i-1) = 1;
if CurPhase == 2
GLI.RecFin(i-1) = 1;
end
CurPhase = 1;
elseif Temp < TempLag && CurPhase ~= 2
GLI.RecStart(i-1) = 1;
if CurPhase == 1
GLI.ProsFin(i-1) = 1;
end
CurPhase = 2;
end
TempLag = Temp;
end
if CurPhase == 1
GLI.ProsFin(end) = 1;
elseif CurPhase == 2
GLI.RecFin(end) = 1;
end
%%%%%%%%%%%%%%%%%%% Create plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
plot(GLI.Dates,GLI.GLI)
colorstr=[0 1 0];
shadedates(GLI.Dates(logical(GLI.ProsStart)),GLI.Dates(logical(GLI.ProsFin)),colorstr)
colorstr=[1 0 0];
shadedates(GLI.Dates(logical(GLI.RecStart)),GLI.Dates(logical(GLI.RecFin)),colorstr)
save a handle to the plotted object:
p = plot(GLI.Dates,GLI.GLI)
and then use this (after the calls to shadedates):
uistack(p,'top')
(I have this from here)

Last plot in subplot becomes over-sized

I am using subplot function of MATLAB. Surprisingly the last plot in each subplot set becomes over-sized. Can anybody help me to resolve this issue? I have experimented with the parameters a little, but no luck. I am not able to post the plot figure.
function plotFluxVariabilityByGene(cRxn,KeggID,geneName)
load iJO1366; % Load the model iJO1366
%Find 'Gene' associated reactions from 'model'
reactions = rxnNamesFromKeggID(model,KeggID);
nCheck = 0; % Initialize counter
% Determine initial subplot dimensions
[R C setSize] = subplotSize(numel(reactions));
for n = 1 : numel(reactions)
% Get the name of nth reaction
rxn = reactions{n};
% Define the array for control reaction fluxes
cRxnArray = getCrxnArray(model,cRxn);
% Initialize storage for lower and upper limit-values
L = []; U = []; Avg = [];
% Get the fluxVariability values
for i = 1 : numel(cRxnArray)
modelMod = changeRxnBounds(model,cRxn,cRxnArray(i),'b');
[L(i) U(i)] = fluxVariability(modelMod,100,'max',{rxn});
Avg(i) = (L(i) + U(i))/2;
%fprintf('mthfcFlux = %f; Li = %f; Ui = %f\n',array(i),L(i),U(i));
end
% adjust the subplot number
nCheck = nCheck + 1;
% Determine the range of n to be saved in one file
if nCheck == 1
start = n;
elseif nCheck == setSize;
stop = n;
end
subplot(R,C,nCheck)
plot(cRxnArray,L,'-r','LineWidth',1); hold on;
plot(cRxnArray,L,'^r','MarkerSize',3,'LineWidth',2);
plot(cRxnArray,U,'-.b','LineWidth',1);
plot(cRxnArray,U,'^b','MarkerSize',2,'LineWidth',2);
plot(cRxnArray,Avg,'-','Color',[0.45,0.45,0.45],'LineWidth',2.5);
% Label X and Y axes
%xlabel([cRxn ' Flux']);
%ylabel(['fluxVariability ' char(rxn)]);
xlabel('Flux');
ylabel('fluxVariability');
hold off;
% Adjust X and Y axes limits
%xmn = min(cRxnArray) - ((max(cRxnArray) - min(cRxnArray))*0.05);
%xmx = max(cRxnArray) + ((max(cRxnArray) - min(cRxnArray))*0.05);
%ymn = min([U L]) - ((max([U L]) - min([U L]))*0.05);
%ymx = max([U L]) + ((max([U L]) - min([U L]))*0.05);
%if xmn ~= xmx
% xlim([xmn xmx]);
%end
%if ymn ~= ymx
% ylim([ymn ymx]);
%end
% Print which reactions are done
fprintf('\n......done for %s',char(rxn));
% If 'setSize' subplots are done then save the set in a file
if nCheck == setSize
saveas(gcf,['TEST/' cRxn 'flux-Vs-' geneName '_fluxVariability' num2str(start) '-' num2str(stop) '.fig']);
saveas(gcf,['TEST/' cRxn 'flux-Vs-' geneName '_fluxVariability' num2str(start) '-' num2str(stop) '.eps']); close(gcf);
% Determine initial subplot dimensions
[R C setSize] = subplotSize(numel(reactions)-n);
% Return nCheck to zero;
nCheck = 0;
end
end
% If nCheck is not equal to 16 then there are subplot that is not saved
% inside the for loop. Let's save it here.
if nCheck ~= setSize
stop = n;
saveas(gcf,['TEST/' cRxn 'flux-Vs-' geneName '_fluxVariability' num2str(start) '-' num2str(stop) '.fig']);
saveas(gcf,['TEST/' cRxn 'flux-Vs-' geneName '_fluxVariability' num2str(start) '-' num2str(stop) '.eps']); close(gcf);
end
fprintf('\nAll done\n');
end
%####################################################
%# Other functions ##
%####################################################
function rxnNames = rxnNamesFromKeggID(model,KeggID)
% Find 'Gene' associated reactions from 'model'
associatedRxns = findRxnsFromGenes(model,KeggID);
% Extract the reaction details from the structure to a cell
rxnDetails = eval(sprintf('associatedRxns.%s',KeggID));
% Extract only the reaction names from the cell
rxnNames = rxnDetails(:,1);
end
%####################################################
function cRxnArray = getCrxnArray(model,cRxn)
% Define the solver
changeCobraSolver('glpk');
% Find solution for the model
sol = optimizeCbModel(model);
% Change the objective of the default model to 'cRxn'
tmpModel = changeObjective(model,cRxn);
% Find slution for the changed model. This gives the maximum and
% minimum possible flux through the reaction 'cRxn' when the model is
% still viable
%solMax = optimizeCbModel(tmpModel,'max');
solMin = optimizeCbModel(tmpModel,'min');
% Create an array of 20 euqally spaced flux values between 'solMin' and
% 'sol.x'
%array = linspace(solMin.f,solMax.f,10);
cRxnArray = linspace(solMin.f,sol.x(findRxnIDs(model,cRxn)),20);
end
%####################################################
function [R C setSize] = subplotSize(remainingPlots)
% Sets number of columns and rows to 3 if total subplot >= 9
if remainingPlots > 7
R = 3; C = 3; setSize = 9;
elseif remainingPlots < 7
R = 2; C = 3; setSize = 6;
elseif remainingPlots < 5
R = 2; C = 2; setSize = 4;
elseif remainingPlots < 4
R = 1; C = 3; setSize = 3;
elseif remainingPlots < 3
R = 1; C = 2; setSize = 2;
end
end
%####################################################
My subplot looks like this:
I suspect its because you are calling subplotSize a second time inside your loop. This could be changing your R and C variables.
I would advise to check the R and C variables at the subplot command on each loop.

Shidoku solver matlab code

I'm trying to write a Shidoku ( smaller and easier 4x4 variant of Sudoku) solver code in MATLAB.
I have found some soduko solver (9x9) but i could't revise them to be suitable for my problem. For example:
% Solving Sudoku Using Recursive Backtracking
function X = sudoku(X)
% SUDOKU Solve Sudoku using recursive backtracking.
% sudoku(X), expects a 9-by-9 array X.
% Fill in all “singletons”.
% C is a cell array of candidate vectors for each cell.
% s is the first cell, if any, with one candidate.
% e is the first cell, if any, with no candidates.
[C,s,e] = candidates(X);
while ~isempty(s) && isempty(e)
X(s) = C{s};
[C,s,e] = candidates(X);
end
% Return for impossible puzzles.
if ~isempty(e)
return
end
% Recursive backtracking.
if any(X(:) == 0)
Y = X;
z = find(X(:) == 0,1); % The first unfilled cell.
for r = [C{z}] % Iterate over candidates.
X = Y;
X(z) = r; % Insert a tentative value.
X = sudoku(X); % Recursive call.
if all(X(:) > 0) % Found a solution.
return
end
end
end
% ------------------------------
function [C,s,e] = candidates(X)
C = cell(9,9);
tri = #(k) 3*ceil(k/3-1) + (1:3);
for j = 1:9
for i = 1:9
if X(i,j)==0
z = 1:9;
z(nonzeros(X(i,:))) = 0;
z(nonzeros(X(:,j))) = 0;
z(nonzeros(X(tri(i),tri(j)))) = 0;
C{i,j} = nonzeros(z)';
end
end
end
L = cellfun(#length,C); % Number of candidates.
s = find(X==0 & L==1,1);
e = find(X==0 & L==0,1);
end % candidates
end % sudoku
Any help will be helpful.
Just reduce the problem dimensionality from 3 to 2 (I know now that it is said "9x9" instead of "3x3", but the important dimensional number for the puzzle is N=3):
% SHIDOKU Solve Shidoku using recursive backtracking.
% shidoku(X), expects a 4-by-4 array X.
function X = shidoku(X)
[C,s,e] = candidates(X);
while ~isempty(s) && isempty(e)
X(s) = C{s};
[C,s,e] = candidates(X);
end;
if ~isempty(e)
return
end;
if any(X(:) == 0)
Y = X;
z = find(X(:) == 0,1);
for r = [C{z}]
X = Y;
X(z) = r;
X = shidoku(X);
if all(X(:) > 0)
return;
end;
end;
end;
% ------------------------------
function [C,s,e] = candidates(X)
C = cell(4,4);
bi = #(k) 2*ceil(k/2-1) + (1:2);
for j = 1:4
for i = 1:4
if X(i,j)==0
z = 1:4;
z(nonzeros(X(i,:))) = 0;
z(nonzeros(X(:,j))) = 0;
z(nonzeros(X(bi(i),bi(j)))) = 0;
C{i,j} = transpose(nonzeros(z));
end;
end;
end;
L = cellfun(#length,C); % Number of candidates.
s = find(X==0 & L==1,1);
e = find(X==0 & L==0,1);
end % candidates
end % shidoku