python遗传算法八皇后_用遗传算法解八皇后问题

此算法收敛速度还可以,基本在1万代之内就能找到解

主程序

clear;

clc;

%%

%八皇后问题,8X8的棋盘上,放置8个皇后,使之两两都不能攻击

%初始的状态,随机在棋盘上放置8个皇后,每列放一个

n = 8; %8皇后

%%

%用遗传算法计算

%先随机获得几个个体,形成一个种群

%这个种群有10个个体

No_of_people = 10;

people = randi(n,[No_of_people,n]);

%计算每个初始种群的h值

people_h = ones(No_of_people,1);

for i = 1:No_of_people

people_h(i) = fun_c(people(i,:));

end

%进化了多少代,由G来统计

G = 1;

G_max = 1e5;

plt = zeros(1,G_max);

while prod(people_h)~=0 && G<=G_max

%精英保留策略,保留初始种群中1/100的精英个体

%保留多少个精英

No_elite = fix(No_of_people/100);

if No_elite == 0

No_elite =1;

end

%按照h值选出这些精英

[~,ind] = sort(people_h);

index = ind(1:No_elite);

people_elite = people(index,:);

%计算这个种群中每个个体的优势,以百分比表示,所有个体优势之和为1

adv = people_h ./ sum(people_h);

%从种群中随机选出10对个体,根据个体的优势来选择,优势越大的,被选中的概率越大

people_dad = people;

people_mom = people;

for i=1:No_of_people

pick = ones(2,1);

while pick(1)==pick(2)

pick = randsrc(2,1,[1:No_of_people; adv']);

end

people_dad(i,:) = people(pick(1),:);

people_mom(i,:) = people(pick(2),:);

end

%然后交叉繁殖,染色体交叉。一对夫妇只生一个孩子

for i=1:No_of_people

%随机生成一个交叉位点

p = randi(n-1);

people(i,:) = [people_dad(i,1:p),people_mom(i,p+1:n)];

end

%然后以一定的概率,产生随机突变

for i=1:No_of_people

%随机生成一个突变位点

p_change = rand(1);

p_dot = randi(n);

%设定突变的概率为10%

if p_change <= 0.1

people(i,p_dot) = randi(n);

end

end

%更新种群的h值

for i = 1:No_of_people

people_h(i) = fun_c(people(i,:));

end

%找出繁殖的后代中最差的个体,个体数量 = 精英数量

[~,ind] = sort(people_h,'descend');

index_bad = ind(1:No_elite);

%删除最差的个体

people(index_bad,:) = [];

%把精英加入种群

people_tmp = [people; people_elite];

people = people_tmp;

%更新种群的h值

for i = 1:No_of_people

people_h(i) = fun_c(people(i,:));

end

plt(G) = min(people_h);

G = G + 1;

end

plot(plt(1:G-1));

axis auto;

%%

if prod(people_h)==0

disp('遗传算法收敛');

index = find(people_h == 0);

disp('可能的解为 ');

disp(people(index,:));

else

disp('遗传算法不收敛');

end

disp(['经历了 ',num2str(G-1),' 代遗传']);

function [h] = fun_c(state)

%根据一个状态,评价它的代价函数

h = 0;

n = length(state);

%%

%每列的状态,看有多少个能互相攻击,每两两攻击算一次

for i=1:n

count = length(find(state == i));

if count > 1;

h = h + nchoosek(count,2);

end

end

%%

%将state转换成nXn矩阵

state_full = zeros(n,n);

for i=1:n

for j=1:n

if j == state(i)

state_full(i,j) = 1;

end

end

end

%%

%每个左斜对角的状态,看有多少个能互相攻击,每两两攻击算一次

i=1;

j=1;

add = 0;

while i0 && j>0

%计算左斜对角每条线有多少个皇后

count = fun_calc_left(i,j,n,state_full);

if count > 1;

h = h + nchoosek(count,2);

end

if add == 0;

j = j + 1;

elseif add == 1;

i = i + 1;

end

add = ~add;

end

%%

%每个右斜对角的状态,看有多少个能互相攻击,每两两攻击算一次

i=1;

j=n;

add = 0;

while i0 && j>0

%计算右斜对角有多少个皇后

count = fun_calc_right(i,j,n,state_full);

if count > 1;

h = h + nchoosek(count,2);

end

if add == 0;

j = j - 1;

elseif add == 1;

i = i + 1;

end

add = ~add;

end

end

function count = fun_calc_left(i,j,n,state_full)

%%

%统计i,j 点,左下角

count = 0;

i_l = i;

i_r = i;

j_l = j;

j_r = j;

while i_l>0 && j_l>0 && i_l

count = count + state_full(i_l,j_l);

i_l = i_l + 1;

j_l = j_l - 1;

end

%%

%右上角的个数

while i_r>0 && j_r>0 && i_r

count = count + state_full(i_r,j_r);

i_r = i_r - 1;

j_r = j_r + 1;

end

%%

%被重复加的,减去

count = count - state_full(i,j);

end

function count = fun_calc_right(i,j,n,state_full)

%%

%统计i,j 点,左上角

count = 0;

i_l = i;

i_r = i;

j_l = j;

j_r = j;

while i_l>0 && j_l>0 && i_l

count = count + state_full(i_l,j_l);

i_l = i_l - 1;

j_l = j_l - 1;

end

%%

%右下角的个数

while i_r>0 && j_r>0 && i_r

count = count + state_full(i_r,j_r);

i_r = i_r + 1;

j_r = j_r + 1;

end

%%

%被重复加的,减去

count = count - state_full(i,j);

end

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值