人工智能实验八数码,TSP算法

找了很多资料,终于查到了两份本人现在能看到比较明白的八数码(C++),TSP算法(matlab)代码,本来想连实验报告一起发的,后来想想算了,就发一下代码和自己理解写的注释,希望对校友有所帮助。

1.八数码

void move(int flag,Node *node)

{                                                    //向四个方向扩展 ,flag用1表示右,2表示下,3表示左,4表示上

    int temp;      

    if(flag==1&&node->x>0)

  {                                               //靠右边,向左移动

        Node *n = new Node();

        for(int i=0;i<3;i++)

  {

            for(int j=0;j<3;j++)

  {

                n->a[i][j]=node->a[i][j];            //n接收node矩阵

            }

        }

       

        n->a[node->x][node->y]=node->a[node->x-1][node->y];      //左移

        n->a[node->x-1][node->y]=0;                             //对应位置置0,即置空

        n->x=node->x-1;                                          //改变x的值

        n->y=node->y;                                          //改变y的值

        n->flag=3;                                             //左边

       

        n->father=node;                                         //设node为n的父节点

       

        n->g=node->g+1;                                         //  求 g(),步骤加一,所以g只需+1

        n->h=a_start_h(n);                                      //求n节点的h

        n->f=n->g+n->h;                                         //f=g+h

       

        open_cnt++;                                               //扩展的节点

        open_node_cnt++;                                          //节点个数

        open[open_cnt].np=n;                                     //添加到open表

        open[open_cnt].f=n->f;                                   //  求 f()

       

    }                                                            //以下三种情况同理,注释简略

  else if(flag==2&&node->y<2)

      {                                                        //靠下,上移

        Node *n = new Node();

        for(int i=0;i<3;i++)

  {

            for(int j=0;j<3;j++)

  {

                n->a[i][j]=node->a[i][j];

            }

        }

       

        n->a[node->x][node->y]=node->a[node->x][node->y+1];          //下移

        n->a[node->x][node->y+1]=0;

        n->x=node->x;

        n->y=node->y+1;

        n->flag=4;

        n->father=node;

        n->g=node->g+1;                                             //  求 g()

        n->h=a_start_h(n);

        n->f=n->g+n->h;

        open_cnt++;

        open_node_cnt++;

        open[open_cnt].np=n;                                         //添加到open表

        open[open_cnt].f=n->f;                                       //  求 f()

       

    }

  else if(flag==3&&node->x<2)

      {                                                          //靠左边,向右移

        Node *n = new Node();

        for(int i=0;i<3;i++)

  {

            for(int j=0;j<3;j++)

  {

                n->a[i][j]=node->a[i][j];

            }

        }

       

        n->a[node->x][node->y]=node->a[node->x+1][node->y];           //右移

        n->a[node->x+1][node->y]=0;

        n->x=node->x+1;

        n->y=node->y;  

        n->flag=1;

        n->father=node;

        n->g=node->g+1;                                              //  求 g()

        n->h=a_start_h(n);

        n->f=n->g+n->h;

        open_cnt++;

        open_node_cnt++;

        open[open_cnt].np=n;                                         //添加到open表

        open[open_cnt].f=n->f;                                       //  求 f()

       

    }

  else if(flag==4&&node->y>0)

      {                                                           //靠上,下移

        Node *n = new Node();

        for(int i=0;i<3;i++)

  {

            for(int j=0;j<3;j++)

  {

                n->a[i][j]=node->a[i][j];

            }

        }

       

        n->a[node->x][node->y]=node->a[node->x][node->y-1];

        n->a[node->x][node->y-1]=0;

        n->x=node->x;

        n->y=node->y-1;    

        n->flag=2;

        n->father=node;

        n->g=node->g+1;                                                //  求 g()

        n->h=a_start_h(n);

        n->f=n->g+n->h;

        open_cnt++;

        open_node_cnt++;

        open[open_cnt].np=n;                                           //添加到open表

        open[open_cnt].f=n->f;                                         //  求 f()

    }   

}

void expand(Node *node)

{                                                                        //节点扩展   

    for(int i=1;i<=4;i++)

  {                                                                 //向4个方向扩展

        if(i!=node->flag)                                               

     move(i,node);

    }

}

int main()

{

    input();

    open[0].np = &start;                                              //start放入open表

    open_node_cnt=1;                                                  //从开始状态

    if(isable())                                                        //判断是否有解

  {

        while(true)

  {                                                              //open表不为空

            if(isend(open[0].np))                                       //当找到目标节点时,输出

  {

              printf("\n路径:\n");

                show(open[0].np);

                break;

            }

            expand(open[0].np);                                         //扩展最优节点的子节点

            open[0].np=NULL;

            open[0].f=-1;

            open_node_cnt--;                                              //open表数量-1

            sort(open);                                                   //open表排序

        }

    }

  else cout<<"无解";

        system("pause");

}

Asuanfa

int a_h(Node *node)

{                                                 //求 h()计算当前节点与目标节点相比数码不同的位置个数

    int old_x,old_y,end_x,end_y;

    int h=0;

        for(int i=0;i<3;i++)

  {

            for(int j=0;j<3;j++)

  {

                if(node->a[i][j]!=end.a[i][j])      //对应位置不同时

  {                                

                   h++;

                }           

               

            }

        }

 

    return h;

2.TSP

%%

function GaTSP

City_Num = 10;                                                             % 城市数目,可以任意数字,这里取10

[distant, location] = tsp(City_Num);                                       % disstat为城市之间相互的距离,location为各城市的坐标

n = 10;                                                                    %n为初始种群大小,随意设置大小

gn_Max = 600;                                                              % 最大代数,可改变

cross_Prob = 0.9;                                                          % 交叉概率,可改变  probably简记prob

mut_Prob = 0.2;                                                            % 变异概率,可改变  mutate

                                                                           % 随机产生初始种群

pn = zeros(n, City_Num);                                                   % population 为初始种群,包括多条染色体 population简记pn

for i = 1 : n

    pn(i,:) = randperm(City_Num);                                          %randperm函数是返回1到n随机打乱得到的一个数字序列

end

[~, cumulativeProbs] = calPopulationValue(pn, distant);                    % 计算种群每条染色体的累计概率  cumulativeProbs

gn_Num = 1;                                                                %第一代   generation简记gn

gn_MeanValue = zeros(gn_Num, 1);                                           % 每一代的平均距离

gn_MaxValue = zeros(gn_Num, 1);                                            % 每一代的最短距离

best_Route = zeros(n, City_Num);                                           % 最佳路径

new_Pn = zeros(n, City_Num);                                               % 新的种群

while gn_Num <= gn_Max                                                     %当前代数未到达最大代数时,继续循环

   for j = 1 : 2 : n                                                       %染色体两两交叉,所以步长为2

      selected_Chromos = select(cumulativeProbs);                          % 选择操作,选出两条需要交叉编译的染色体,即父本母本

      crossed_Chromos = cross(pn, selected_Chromos, cross_Prob);           % 交叉操作,返回交叉后的染色体  染色体Chromosome

      new_Pn(j, :) = mut(crossed_Chromos(1, :),mut_Prob);                  % 对交叉后的染色体进行变异操作

      new_Pn(j + 1, :) = mut(crossed_Chromos(2, :), mut_Prob);             % 对交叉后的染色体进行变异操作

   end

  

   pn = new_Pn;                                                            %产生了新的种群,进行换代

  

   [populationValue, cumulativeProbs] = calPopulationValue(pn, distant);   % 计算新种群的适应度

                                             

   [fmax, nmax] = max(populationValue);                                    % 记录当前代最好和平均的适应度                            

   gn_MeanValue(gn_Num) = 1 / mean(populationValue);                       % 因为计算适应度时取距离的倒数,这里面取最大的倒数,即最短的距离

   gn_MaxValue(gn_Num) = 1 / fmax;  

   bestChromo = pn(nmax, :);                                               % 前代最佳染色体,即对应的路径

   best_Route(gn_Num, :) = bestChromo;                                     % 记录每一代的最佳染色体,也就是存储最佳线路

   drawTSP(location, bestChromo, gn_MaxValue(gn_Num), gn_Num, 0);          %绘图

   gn_Num = gn_Num + 1;                                                    %代数加一

end

[bestValue,index] = min(gn_MaxValue);

drawTSP(location, best_Route(index, :), bestValue, index,1);

figure(2);

plot(gn_MaxValue, 'r'); 

hold on;

plot(gn_MeanValue, 'b');

grid;

title('搜索过程');

legend('最优解', '平均解');

fprintf('遗传算法得到的最短距离: %.2f\n', bestValue);

end

%

%------------------------------------------------

                                                                           % 计算所有染色体的适应度

function [chromoValues, cumulativeProbs] = calPopulationValue(pn, distant)

n = size(pn, 1);                                                           % 读取种群大小10

chromoValues = zeros(n, 1);                                                %chromoValues存储每条染色体适应度

for i = 1 : n

    chromoValues(i) = CalDist(distant, pn(i, :));                          % 计算每条染色体的适应度

end

chromoValues = 1./chromoValues';                                           % 因为距离越小,选取的概率越高,所以取距离倒数,语法./要注意,'转置

                                                                           % 根据个体的适应度计算其被选择的概率

fsum = 0;

for i = 1 : n                                                              %计算分母fsum

                                                                           % 乘以10次方的原因是让好的个体被选取的概率更大(因为适应度取距离的倒数,若不乘次方,则个体相互之间的适应度差别不大),换成一个较大的数也行

    fsum = fsum + chromoValues(i)^10;  

end

                                                                           % 计算单个概率

probs = zeros(n, 1);

for i = 1: n

    probs(i) = chromoValues(i)^10 / fsum;

end

% 计算累积概率

cumulativeProbs = zeros(n,1);

cumulativeProbs(1) = probs(1);

for i = 2 : n

    cumulativeProbs(i) = cumulativeProbs(i - 1) + probs(i);

end

cumulativeProbs = cumulativeProbs';                                        %转置

end

%--------------------------------------------------

                                                                           %“选择”操作,返回所选择染色体在种群中对应的位置

                                                                           % cumulatedPro 所有染色体的累计概率

function selectedChromoNums = select(cumulatedPro)

selectedChromoNums = zeros(2, 1);

                                                                           % 从种群中选择两个个体,最好不要两次选择同一个个体

for i = 1 : 2

   r = rand;                                                               % 产生一个随机数

   prand = cumulatedPro - r;

   j = 1;

   while prand(j) < 0

       j = j + 1;

   end

   selectedChromoNums(i) = j;                                              % 选中个体的序号

   if i == 2 && j == selectedChromoNums(i - 1)                             % 若相同就再选一次

       r = rand;                                                           % 产生一个随机数

       prand = cumulatedPro - r;

       j = 1;

       while prand(j) < 0

           j = j + 1;

       end

   end

end

end

%------------------------------------------------

% “交叉”操作

function crossedChromos = cross(population, selectedChromoNums, crossProb)

length = size(population, 2);                                              % 染色体的长度

crossProbc = crossMuteOrNot(crossProb);                                    %根据交叉概率决定是否进行交叉操作,1则是,0则否

crossedChromos(1,:) = population(selectedChromoNums(1), :);                %把要交叉的染色体从种群中取出来

crossedChromos(2,:) = population(selectedChromoNums(2), :);

if crossProbc == 1

   c1 = round(rand * (length - 2)) + 1;                                    %在[1,bn - 1]范围内随机产生一个交叉位 c1  round函数用于舍入到最接近的整数

   c2 = round(rand * (length - 2)) + 1;                                    %在[1,bn - 1]范围内随机产生一个交叉位 c2

   chb1 = min(c1, c2);

   chb2 = max(c1,c2);

   middle = crossedChromos(1,chb1+1:chb2);                                 % 两条染色体 chb1 到 chb2 之间互换位置

   crossedChromos(1,chb1 + 1 : chb2)= crossedChromos(2, chb1 + 1 : chb2);

   crossedChromos(2,chb1 + 1 : chb2)= middle;

   for i = 1 : chb1                                                        % 看交叉后,染色体上是否有相同编码的情况(路径上重复出现两个城市)。若有,则该编码不参与交叉

       while find(crossedChromos(1,chb1 + 1: chb2) == crossedChromos(1, i))

           location = find(crossedChromos(1,chb1 + 1: chb2) == crossedChromos(1, i));

           y = crossedChromos(2,chb1 + location);

           crossedChromos(1, i) = y;

       end

       while find(crossedChromos(2,chb1 + 1 : chb2) == crossedChromos(2, i))

           location = find(crossedChromos(2, chb1 + 1 : chb2) == crossedChromos(2, i));

           y = crossedChromos(1, chb1 + location);

           crossedChromos(2, i) = y;

       end

   end

   for i = chb2 + 1 : length

       while find(crossedChromos(1, 1 : chb2) == crossedChromos(1, i))

           location = logical(crossedChromos(1, 1 : chb2) == crossedChromos(1, i));

           y = crossedChromos(2, location);

           crossedChromos(1, i) = y;

       end

       while find(crossedChromos(2, 1 : chb2) == crossedChromos(2, i))

           location = logical(crossedChromos(2, 1 : chb2) == crossedChromos(2, i));

           y = crossedChromos(1, location);

           crossedChromos(2, i) = y;

       end

   end

end

end

%--------------------------------------------------

                                                                           %“变异”操作

                                                                           % choromo 为一条染色体

function snnew = mut(chromo,muteProb)

length = size(chromo, 2);                                                  % 染色体的的长度

snnew = chromo;

muteProbm = crossMuteOrNot(muteProb);                                      % 根据变异概率决定是否进行变异操作,1则是,0则否

if muteProbm == 1

    c1 = round(rand*(length - 2)) + 1;                                     % 在 [1, bn - 1]范围内随机产生一个变异位

    c2 = round(rand*(length - 2)) + 1;                                     % 在 [1, bn - 1]范围内随机产生一个变异位

    chb1 = min(c1, c2);

    chb2 = max(c1, c2);

    x = chromo(chb1 + 1 : chb2);

    snnew(chb1 + 1 : chb2) = fliplr(x);                                    % 变异,则将两个变异位置的染色体倒转   fliplr函数主要的作用是将矩阵进行左右翻转。

end

end

% 根据变异或交叉概率,返回一个 0 或 1 的数

function crossProbc = crossMuteOrNot(crossMuteProb)

test(1: 100) = 0;

l= round(100 * crossMuteProb);

test(1 : l) = 1;

n = round(rand * 99) + 1;

crossProbc = test(n);

end

%------------------------------------------------

% 计算一条染色体的适应度

% dislist 为所有城市相互之间的距离矩阵

% chromo 为一条染色体,即一条路径

function chromoValue = CalDist(distant, chromo)

Distant_sum = 0;

nlen = size(chromo, 2);                                                    % 染色体的长度

for i = 1 : (nlen - 1)

    Distant_sum = Distant_sum + distant(chromo(i), chromo(i + 1));

end

Distant_sum = Distant_sum + distant(chromo(nlen), chromo(1));              %线路要闭合

chromoValue = Distant_sum;

end

%------------------------------------------------

% 画图

% Clist 为城市坐标

% route 为一条路径

function drawTSP(Clist, route, generationValue, generationNum,isBestGeneration)

CityNum = size(Clist, 1);

for i = 1 : CityNum - 1

    plot([Clist(route(i), 1),Clist(route(i + 1), 1)], [Clist(route(i),2),Clist(route(i+1),2)],'ms-','LineWidth',2,'MarkerEdgeColor','k','MarkerFaceColor','g');

    text(Clist(route(i), 1),Clist(route(i), 2), ['  ', int2str(route(i))]);

    text(Clist(route(i+1), 1),Clist(route(i + 1), 2), ['  ', int2str(route(i+1))]);

    hold on;

end

plot([Clist(route(CityNum), 1), Clist(route(1), 1)], [Clist(route(CityNum), 2), Clist(route(1), 2)],'ms-','LineWidth',2,'MarkerEdgeColor','k','MarkerFaceColor','g');

title([num2str(CityNum),'城市TSP']);

                                                          

    if isBestGeneration == 0

        text(0, 0, ['第 ',int2str(generationNum),' 代','  最短距离为 ', num2str(generationValue)]);

    else

        text(0, 0, ['最终搜索结果:最短距离 ',num2str(generationValue),', 在第 ', num2str(generationNum),' 代达到']);

    end

hold off;

pause(0.005);

end

%------------------------------------------------

                                                                           %城市位置坐标

function [DLn, cityn] = tsp(n)

DLn = zeros(n, n);

    city10 = [0.444 0.4439;0.8439 0.1463;0.1707 0.2293;0.4293 0.761;0.5171 0.9414;

        0.8732 0.6536;0.5878 0.5219;0.8488 0.3609;0.683 0.2536;0.6195 0.2634];

    for i = 1 : 10

        for j = 1 : 10

            DLn(i, j) = ((city10(i,1)-city10(j,1))^2 + (city10(i,2)-city10(j,2))^2)^0.5;

        end

    end

    cityn = city10;

end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值