数学建模--基于遗传算法求解数独
来源:互联网 发布:股票涨跌原理 知乎 编辑:程序博客网 时间:2024/06/03 19:00
求解数独网上有很多算法,由于最近在学习遗传算法,所以尝试通过遗传算法来求解数独。
遗传算法求解数独步骤如下
1.初始化化种群
首先需要产生较优的初始种群,以减少进化代数,如果没有较优的初始种群会加大后面运算压力。为了得到较优的初始种群,设置一下规则(1)、每个方格的数字不重复;
(2)、尽可能使填入的数字与所在行或列的数字不重复。
根据以上规则得到一定数量的初始九宫格,然后将每个方格缺的数字按从上到下、从左到右的顺序连在一次作为染色体。
2、交叉
将染色体随机两两组合,随机取两个染色体中间相同的位置进行交换,交叉完后,将未交叉的重复元素用另一个染色体的重复的元素交换(因为该染色体重复的元素就是另一个染色体缺少的元素,元素守恒)。
3、变异
按变异率在种群中随机选择一定数量的个体,随机产生一个变异节点(一一个九宫格的方格作为一个节点),将该节点左右翻转。
4、选择
将父代、子代、变异代三部分染色体合在一起,计算每个染色体还原到九宫格中行和列重复数字的个数,初始分为8*(9+9)=144,每重复一次减去一分。选出分数最高一部分作为下一轮进化的父代。进化到一定程度,出现分数等于144时,退出进化。
matlab代码实现如下:
clc,cleartic;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 endendSuNNum;%按从上到下,从左往右的顺序保存每个方格所缺的数字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:SuNNumL(i) x1=xtab(SuNNumP(i,j))+3*xtab1(i); y1=ytab(SuNNumP(i,j))+3*ytab1(i); v1=find(SuP(x1,:,s)==SuNNum(i,rand1(pf))); v2=find(SuP(:,y1,s)==SuNNum(i,rand1(pf))); %如果在行或列没有重复的数字则将该数字填入九宫格 %否则将从后面往前取一个数字填入九宫格 if isempty(v1) && isempty(v2) SuP(x1,y1,s)=SuNNum(i,rand1(pf)); pf=pf+1; else SuP(x1,y1,s)=SuNNum(i,rand1(pl)); pl=pl-1; end end endendGe=zeros(9,9,w);for s=1:w for i=1:9 for j=1:SuNNumL(i) x1=xtab(SuNNumP(i,j))+3*xtab1(i); y1=ytab(SuNNumP(i,j))+3*ytab1(i); Ge(i,j,s)=SuP(x1,y1,s); %将SuP中的空格位置的数字取出 end end Ge(:,:,s)=Ge(:,:,s)';endGe(Ge==0)=[];%去除Ge中的零元素Ge2=zeros(w,sum(SuNNumL));for s=1:w Ge2(s,:)=Ge((s-1)*sum(SuNNumL)+1:s*sum(SuNNumL)); %将Ge切分为w个染色体end%种群初始化结束,Ge2保存种群中的所有染色体while true %交叉 Ge2Son=Ge2; rand2=zeros(2,w); rand3=randperm(w); rand2(1,:)=1+floor(sum(SuNNumL)*rand(1,w)); rand2(2,:)=1+floor(sum(SuNNumL)*rand(1,w)); %调整rand2的大小顺序,rand(1,)<=rand(2,) for s=1:w if rand2(1,s)>rand2(2,s) tempc=rand2(1,s); rand2(1,s)=rand2(2,s); rand2(2,s)=tempc; end end %根据rand3随机序列、以rand(1,)作为低位交叉点、以rand(2,)作为高位交叉点进行两个个体之间基因交叉 for s=1:2:w-1 tempc1=Ge2Son(rand3(s),rand2(1,s):rand2(2,s)); Ge2Son(rand3(s),rand2(1,s):rand2(2,s))=Ge2Son(rand3(s+1),rand2(1,s):rand2(2,s)); Ge2Son(rand3(s+1),rand2(1,s):rand2(2,s))=tempc1; end %去除染色体各节点的重复元素 SuNNumLS=cumsum(SuNNumL); Lowid=zeros(1,w-1); Highid=zeros(1,w-1); for s=1:2:w-1 %找出低位交叉点所在的九宫格 for i=1:9 if rand2(1,s)<SuNNumLS(i) Lowid(s)=i; break; elseif i==1 Lowid(s)=9; end end %找出高位交叉点所在的九宫格 for i=9:-1:1 if rand2(2,s)>SuNNumLS(i) Highid(s)=i+1; break; elseif i==1 Highid(s)=1; end end Lowid(s+1)=Lowid(s); Highid(s+1)=Highid(s); %获取交叉点所在节点组别 end %Lowid(Lowid==0)=[]; %Highid(Highid==0)=[]; %tabulate Getemp1=zeros(9,9); Getemp2=zeros(9,9); %%%%%%%%%%%%%%%%%%%%%%%%%%% for s=1:2:w for i=1:9 Getemp1(i,1:SuNNumL(i))=Ge2Son(rand3(s),SuNNumLS(i)-SuNNumL(i)+1:SuNNumLS(i)); Getemp2(i,1:SuNNumL(i))=Ge2Son(rand3(s+1),SuNNumLS(i)-SuNNumL(i)+1:SuNNumLS(i)); %将染色体以节点为单位切分 end SL1=tabulate(Getemp1(Lowid(s),:)); temp= SL1(:,1)~=0;%去除数字为零结果 SL1=SL1(temp,:); SL1num=SL1(SL1(:,2)==2,1);%找出出现两次的数字 SL2=tabulate(Getemp2(Lowid(s),:)); temp= SL2(:,1)~=0; SL2=SL2(temp,:); SL2num=SL2(SL2(:,2)==2,1); %如果有出现两次的数字,则将父代与母代的出现的数字交换 if (~isempty(SL1num)) && (length(SL1num)==length(SL2num)) for i=1:length(SL1num) Getemp1(Lowid(s),find(Getemp1(Lowid(s),:)==SL1num(i),1))=SL2num(i); Getemp2(Lowid(s),find(Getemp2(Lowid(s),:)==SL2num(i),1))=SL1num(i); end end SH1=tabulate(Getemp1(Highid(s),:)); temp= SH1(:,1)~=0;%去除数字为零结果 SH1=SH1(temp,:); SH1num=SH1(SH1(:,2)==2,1);%找出出现两次的数字 SH2=tabulate(Getemp2(Highid(s),:)); temp=SH2(:,1)~=0; SH2=SH2(temp,:); SH2num=SH2(SH2(:,2)==2,1); %如果有出现两次的数字,则将父代与母代的出现的数字交换 if ~isempty(SH1num) && (length(SH1num)==length(SH2num)) for i=1:length(SH1num) Getemp1(Highid(s),find(Getemp1(Highid(s),:)==SH1num(i),1))=SH2num(i); Getemp2(Highid(s),find(Getemp2(Highid(s),:)==SH2num(i),1))=SH1num(i); end end for i=1:9 Ge2Son(rand3(s),SuNNumLS(i)-SuNNumL(i)+1:SuNNumLS(i))=Getemp1(i,1:SuNNumL(i)); Ge2Son(rand3(s+1),SuNNumLS(i)-SuNNumL(i)+1:SuNNumLS(i))=Getemp2(i,1:SuNNumL(i)); %将去除重复元素后的节点恢复到染色体 end end %交叉结束,子代为Ge2Son %变异 p=0.1;%变异率 Munum=floor(p*w);%变异个体数 rand4=randperm(w);%变异个体的随机序列 Ge2Mu=zeros(Munum,sum(SuNNumL)); Getemp=zeros(9,9); for i=1:Munum Ge2Mu(i,:)=Ge2(rand4(i),:); for j=1:9 Getemp(j,1:SuNNumL(j))=Ge2Mu(i,SuNNumLS(j)-SuNNumL(j)+1:SuNNumLS(j)); end rand5=1+floor(9*rand(1,1));%变异节点随机序号 Getemp(rand5,1:SuNNumL(rand5))=Getemp(rand5,SuNNumL(rand5):-1:1);%将节点翻转 for j=1:9 Ge2Mu(i,SuNNumLS(j)-SuNNumL(j)+1:SuNNumLS(j))=Getemp(j,1:SuNNumL(j)); end %将切分的染色体还原 end %变异结束,GeMu为变异得到的个体 G(1:w,1:SuNNumLS(9))=Ge2; G(w+1:2*w,1:SuNNumLS(9))=Ge2Son; G(2*w+1:2*w+Munum,1:SuNNumLS(9))=Ge2Mu; GeScore=144*ones(1,2*w+Munum); SuOne=zeros(3,3); for i=1:2*w+Munum n=0; for j=1:9 SuOne=Su(index1(j):index1(j)+2,index2(j):index2(j)+2); for m=1:SuNNumL(j) n=n+1; SuOne(SuNNumP(j,m))=G(i,n); end Su(index1(j):index1(j)+2,index2(j):index2(j)+2)=SuOne; end for j=1:9 SH=tabulate(Su(j,:)); SHSame=SH(SH(:,2)>1,2)-1; GeScore(i)=GeScore(i)-sum(SHSame); end for j=1:9 SL=tabulate(Su(:,j)); SLSame=SL(SL(:,2)>1,2)-1; GeScore(i)=GeScore(i)-sum(SLSame); end end score=sort(GeScore); score(1:length(GeScore))=score(length(GeScore):-1:1);%降序排列 t1=1; f=1; while f==1 MaxNum=find(GeScore==score(t1)); for j=1:length(MaxNum) Ge2(t1,:)=G(MaxNum(j),:); if t1==w f=0; break; end t1=t1+1; end end BestGe=G(1,:); if score(1)==144 break; end l=l+1endBestGescore(1)toc;
阅读全文
0 0
- 数学建模--基于遗传算法求解数独
- 数独求解算法
- 数独算法求解
- 数独求解算法
- 数独求解算法
- 数独求解算法
- 数学求解之遗传算法
- 数独的求解算法
- 回溯算法求解数独
- MATLAB数学建模(9)-遗传算法工具
- 数独的求解算法 回溯
- 舞蹈链算法与数独求解
- 基于遗传算法求解车辆路径问题
- 数学建模(1)——遗传算法(GA)
- QT编写的数独求解软件、一个数独快速高效的求解算法
- 数独游戏求解
- 求解数独
- 求解数独
- Windows下Python安装与使用
- 在线考试实时拍照系统
- 欢迎使用CSDN-markdown编辑器
- Pandas to_json() 中文乱码,转化为json数组
- 排序
- 数学建模--基于遗传算法求解数独
- Hadoop入门之MapReduce
- 20170716_http协议和web本质
- 6.1面向对象(介绍,类与对象,封装,this关键字,构造方法,static关键字)
- linux修改系统时间和linux查看时区、修改时区的方法
- HTML入门笔记4-段落标签和换行
- 总结(7.10—7.16)
- TensorFlow教程 3 建造神经网络
- Spark-Streaming获取applicationId即scala中获取appid