求解数独网上有很多算法,由于最近在学习遗传算法,所以尝试通过遗传算法来求解数独。
遗传算法求解数独步骤如下
1.初始化化种群
首先需要产生较优的初始种群,以减少进化代数,如果没有较优的初始种群会加大后面运算压力。为了得到较优的初始种群,设置一下规则(1)、每个方格的数字不重复;
(2)、尽可能使填入的数字与所在行或列的数字不重复。
根据以上规则得到一定数量的初始九宫格,然后将每个方格缺的数字按从上到下、从左到右的顺序连在一次作为染色体。
2、交叉
将染色体随机两两组合,随机取两个染色体中间相同的位置进行交换,交叉完后,将未交叉的重复元素用另一个染色体的重复的元素交换(因为该染色体重复的元素就是另一个染色体缺少的元素,元素守恒)。
3、变异
按变异率在种群中随机选择一定数量的个体,随机产生一个变异节点(一一个九宫格的方格作为一个节点),将该节点左右翻转。
4、选择
将父代、子代、变异代三部分染色体合在一起,计算每个染色体还原到九宫格中行和列重复数字的个数,初始分为8*(9+9)=144,每重复一次减去一分。选出分数最高一部分作为下一轮进化的父代。进化到一定程度,出现分数等于144时,退出进化。
matlab代码实现如下:
clc,clear
tic;
Su=[
0 2 0 0 0 5 0 0 0;
3 5 4 0 8 0 1 0 0;
0 9 1 6 2 0 0 5 0;
0 3 9 7 6 2 0 8 0;
0 7 0 0 9 8 0 0 0;
0 0 2 0 3 1 7 9 4;
2 6 7 0 1 9 8 4 5;
0 0 3 8 5 6 0 1 0;
5 0 0 0 7 4 9 3 6;
];
index1=[1 4 7 1 4 7 1 4 7];
index2=[1 1 1 4 4 4 7 7 7];
SuNNum=zeros(9,9);
SuNNumP=zeros(9,9);
SuNNumL=zeros(9,1);
l=0;
for i=1:9
SuOne=Su(index1(i):index1(i)+2,index2(i):index2(i)+2);
v=find(SuOne==0);
SuNNumP(i,1:length(v))=v';
t=0;
for j=1:9
v=find(SuOne==j);
if isempty(v)
t=t+1;
SuNNum(i,t)=j;
SuNNumL(i)=t;
end
end
end
SuNNum;%按从上到下,从左往右的顺序保存每个方格所缺的数字
SuNNumP;%按从上到下,从左往右的顺序保存每个方格所缺的数字的位置
SuNNumL;%按从上到下,从左往右的顺序保存每个方格所缺的数字的长度
%初始化种群
xtab=[1 2 3 1 2 3 1 2 3];
ytab=[1 1 1 2 2 2 3 3 3];
xtab1=[0 1 2 0 1 2 0 1 2];
ytab1=[0 0 0 1 1 1 2 2 2];
w=sum(SuNNumL)*6;%种群大小
SuP=zeros(9,9,w);%w个九宫格
for s=1:w
SuP(:,:,s)=Su;
for i=1:9
pf=1;
pl=SuNNumL(i);
rand1=randperm(SuNNumL(i));
for j=1:SuN