如何利用遗传算法设计博弈AI

很感谢黄岚老师的帮助,在她的指导下完成了论文的书写工作,现已被Ei检索。

之前有过设计五子棋AI的想法,当时想的运用博弈树,一层一层搜索来完成,我的第一版确实也是这么做的。后来看到这个方法已经烂大街,并且衍生出很多变种,改进也很大,于是尝试着创新。

无意中看到一篇文章:遗传算法:内存中的进化,生动的讲解了什么是遗传算法以及作用,我突然觉得可以拿到设计博弈AI里面去,因为遗传算法就是解决复杂运算的一个简单途径,大量的博弈树的搜索往往是不需要的。

考虑了很久,大致的思路就是把双方的博弈步奏用基因型编码,然后判断当时场上的局面,并尝试量化为适应度函数,基因型的长度和博弈的深度成正比,比如A代表人,B代表电脑,那么基因型编码为ABABAB就代表人和电脑各进行3次博弈,运用适应度函数给出适应值,然后将大量的编码进行遗传迭代,最终选择一个最优解。这个最优解可能不是我方局式最优解,但一定是不让人占上风的解,比如你和别人都可以得到一个完美局势,但是他比你先完成布局,你就应该阻止他完成他的部署,这个过程就要在适应度函数里体现,定一个标准,之后在计算适应度里体现出当前局势的分值,值得说明的是不能仅考虑我方的布局的分值,比如按照一种博弈过程我方形式一片大好,对方却在进行毫无意义的布局那么这个博弈过程显然是失败的,博弈的精髓就是互相考虑双方都发挥最大实力的前提下如何战胜对方。

当然这里面还有多细节问题,比如如何量化各种局势、如何保证最优遗传、甚至如何设计编码的深度都值得认真考虑。这里不再详细说明。

附1.与AI对弈的截图

附2.遗传算法简单框架,以计算以下式子为例:

MAX:f(x,y,z)=sin(x)+(1+cos(y+z))^(2+sin(ln(1+abs(tan(y+z))))/(x+y+1))

unit genetic;

interface
uses System.SysUtils, System.Variants, System.Classes,generics.collections,math;

type
 TChromosome=record              //染色体
 gen:array [0..2] of word ;      //基因
 va:single;                      //表现型
 end;

procedure heaps(list:Tlist<single>);  //内置一个堆排序
function  heapadjust(list:Tlist<single>;s,m:integer):boolean; //堆排序筛选

type
 TGenetic=class
   private
   par:Tlist<TChromosome>;       //父代
   char:Tlist<TChromosome>;      //子代
   geneamount:integer;           //基因规模(长度)
   stablecount:integer;
   procedure value(var sample:TChromosome);              //适应函数
   function  select(pro:array of single):integer;    //选择函数(轮盘赌)
   procedure exc(var p1,p2:TChromosome);                 //染色体交叉,变异
   procedure c_original();
   procedure c_Posterity();
   public
   G_varitionrate:single;    //变异概率
   G_crossrate:single;       //交叉概率
   G_oriamount:integer;      //原始父代数目
   G_popmax:integer;         //种群最大数量
   G_selectpar:integer;      //子代选择数目
   G_genecount:integer;      //种群进化代数
   G_maxevolu:integer;       //最大进化代数
   G_gebest:Tlist<Tchromosome>;   //每代最优解
   G_stablecount:integer;    //稳定遗传
   procedure  G_Evolution(); //进化过程
   constructor create;
 end;

implementation

constructor Tgenetic.create;
begin
  par:=Tlist<Tchromosome>.create;
  char:=Tlist<Tchromosome>.create;
  G_gebest:=Tlist<Tchromosome>.create;
  G_oriamount:=1000;
  G_popmax:=2000;
  G_selectpar:=200;
  G_genecount:=0;
  G_maxevolu:=50;
  geneamount:=10000;
  G_varitionrate:=0.01;
  G_crossrate:=1;
  G_stablecount:=10;  //n代不变则认为稳定
end;

procedure Tgenetic.G_Evolution;
begin
  G_genecount:=0;
  c_original;
  while True do
  begin
   c_Posterity;
   inc(G_genecount);
   G_gebest.Add(par.Items[0]);
    if G_genecount>=G_stablecount then
    if (G_gebest.Items[G_genecount-1].va=G_gebest.Items[G_genecount-G_stablecount].va) then break;
    if G_genecount>=G_maxevolu then  break;
end;
end;

procedure Tgenetic.value(var sample:TChromosome);
var
x,y,z:integer;
begin
  x:=sample.gen[0];
  y:=sample.gen[1];
  z:=sample.gen[2];
  sample.va:=sin(x)+power(1+cos(y+z),2+sin(ln(1+abs(tan(y+z))))/(x+y+1));
  //sample.va:=7*x+ln(y+1)+z;
end;

procedure Tgenetic.c_original;
var
i,J:integer;
s:Tchromosome;
begin
 for I := 1 to G_oriamount do
  begin
  for j := 0 to 2 do
  s.gen[j]:=random(geneamount);
  value(s);
  par.Add(s);
  end;
end;

procedure Tgenetic.c_Posterity;
var
i:integer;
sum:double;
prob:array of single;
index:integer;
p1,p2:Tchromosome;
listpx:Tlist<Tchromosome>;
listv,listv0:Tlist<single>;
begin
  listv:=Tlist<single>.create;
  listv0:=Tlist<single>.create;
  listpx:=Tlist<Tchromosome>.create;
  sum:=0;
  setlength(prob,par.count);  //概率
  for I := 0 to par.count-1 do
    sum:=sum+par.items[i].va;
  for I := 0 to par.count-1 do
    prob[i]:=par.items[i].va/sum;
  index:=1;
  while index<=(G_popmax div 2) do
  begin
   p1:=par.Items[select(prob)];
   p2:=par.Items[select(prob)];
   exc(p1,p2);
   value(p1);
   value(p2);
   char.Add(p1);
   char.Add(p2);
   inc(index);
  end;
  par.Clear;
  for I := 0 to char.Count-1 do
   listpx.Add(char.Items[i]);
  char.Clear;
  for I := 0 to listpx.Count-1 do
  begin
   listv.Add(listpx.Items[i].va);
   listv0.Add(listpx.Items[i].va);
  end;
  heaps(listv);          //堆排序
  for I := listpx.Count-G_selectpar to listpx.Count-1 do
   par.Add(listpx.Items[listv0.IndexOf(listv.Items[i])]);
end;

function Tgenetic.select(pro: array of single):integer;
var
i:integer;
num:double;
sum:double;
areap:array of single;                //轮盘
low,high,mid:integer;
begin
  setlength(areap,length(pro));
  i:=0;
  sum:=0;
  for I := 0 to length(pro)-1 do
  begin
   areap[i]:=sum+pro[i];
   sum:=areap[i];
  end;
  num:=randomrange(1,9999999)/10000000;    //轮盘赌算法
  if (num>=0) and (num<=areap[0]) then
  begin
   result:=0;
   exit;
  end;
  if (num>=areap[length(areap)-1]) and (num<=1) then
  begin
   result:=length(areap)-1;
   exit;
  end;
  low:=1;
  high:=length(areap);
 while(low<=high) do             //折半查找
 begin
  mid:=trunc((low+high)/2);
  if (num>=areap[mid-1]) and (num<=areap[mid]) then
  break;
  if num>=areap[mid-1] then low:=mid
  else high:=mid;
 end;
result:=mid;
end;

procedure Tgenetic.exc(var p1,p2: Tchromosome);
var
exn:integer;
i:integer;
temp:integer;
excr:single;
vari:single;
begin
  exn:=random(3);      //3元
  if G_crossrate>random(1000)/1000 then
   for I := exn to 2 do         //交叉
    begin
    temp:=p1.gen[i];
    p1.gen[i]:=p2.gen[i];
    p2.gen[i]:=temp;
    end;
  excr:=random(10000)/10000;
  if excr<G_varitionrate then    //变异
  begin
   i:=random(3);
   p1.gen[i]:=random(geneamount);
  end;
  if excr<G_varitionrate then    //变异
  begin
   i:=random(3);
   p2.gen[i]:=random(geneamount);
  end;
  p1.va:=0;
  p2.va:=0;
end;

procedure heaps(list:Tlist<single>);
var
i:integer;
temp:real;
begin
i:=list.Count div 2;
while i>0 do                             //建成大顶堆
  begin
  heapadjust(list,i,list.Count-1);
  dec(i);
  end;
i:=list.Count;
while i>1 do
  begin
  temp:=list.Items[0];
  list.Items[0]:=list.Items[i-1];
  list.Items[i-1]:=temp;
  heapadjust(list,1,i-1);
  dec(i);
  end;
end;

function heapadjust(list: TList<System.single>; s: Integer; m: Integer):boolean;
var j:integer;
    temp:real;
begin
temp:=list.Items[s-1];
j:=2*s;
while (j<=m) do
  begin
  if (j<m)and(list.Items[j-1]<list.Items[j]) then
  inc(j);
  if temp>=list.Items[j-1] then
  break;
  list.Items[s-1]:=list.Items[j-1];
  s:=j;
  j:=2*j;
  end;
  list.Items[s-1]:=temp;
end;

end.

  

时间: 2024-08-04 11:57:59

如何利用遗传算法设计博弈AI的相关文章

利用MVVM设计快速开发个人中心、设置等模块

我们在做iOS开发过程中,静态页面的开发比开发动态页面更让我们开发者抓狂.因为动态页面通常是一个页面一种cell样式,作为开发者只需要专注于定制好一种样式之后,就可以使用数据填充出较好的界面.而静态cell,则可能因为一个页面有多种cell样式,而且很有可能不是标准的cell样式,需要我们自定义,因此容易写出来的代码容易臃肿和重复.可读性差.这不符合开发者的代码优化原则(不主动重复).我时常会因为开发这种页面抓狂,因为会纠结到底怎么写会让代码可读性好点,写重复代码的机会少点.本文就是我做过的几个

按照所给的程序流程图,分别写出语句覆盖、分支覆盖的测试用例,以及它所覆盖的路径,根据程序流程图,写出代码,用JUnit生成单元测试,并利用前面设计的测试用例进行测试。

语句覆盖:路径:abc ,测试用例:x=3,y=2 分支覆盖:路径:aeg ,测试用例:x=4,y=-1 /** * 2016-04-09 * @author 吴思婷 * DoWork类用来根据程序流程图,写出代码(定义一个类和方法来实现) */ public class DoWork { public void doWork(int x,int y){ int k=0,j=0; if((x<4 || y>0)&&(y>1)){ y=y+1; } else { if(x&

[MATLAB] 利用遗传算法函数求目标函数的最优解

最近接触到了遗传算法以及利用遗传算法求最优解,所以就把这些相关的内容整理记录一下. 一.遗传算法简介(摘自维基百科) 遗传算法(英语:genetic algorithm (GA))是计算数学中用于解决最佳化的搜索算法,是进化算法的一种.进化算法最初是借鉴了进化生物学中的一些现象而发展起来的,这些现象包括遗传.突变.自然选择以及杂交等. 算法 选择初始生命种群 循环 评价种群中的个体适应度 以比例原则(分数高的挑中概率也较高)选择产生下一个种群. 改变该种群(交叉和变异) 直到停止循环的条件满足

利用PYTHON设计计算器功能

通过利用PYTHON 设计处理计算器的功能如: 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 ))- (-4*3)/(16-3*2)) 我的处理计算基本思路是: 解题思路是,需要优先处理内层括号运算--外层括号运算--先乘除后加减的原则:1.正则处理用户输入的字符串,然后对其进行判断,判断计算公式是否有括号,有就先将计算公式进行正则处理,先获取最里层的每一个数据,然后一一计算 所要用到的正则是: inner

设计软件AI学习体会及图片

喜欢设计行业,在学习一些软件,现在在学习AI 这几天照着一些照片做的图标与绘制的图形,希望能得到指点.   通过几天学习发现AI在处理logo上面真的强大,具有PS不能比拟的效果,AI做出的图标,logo等放大不会失真就是一个很实用的功能,因为通过近段时间学习,了解到在设计行业,客户的要求就是logo大,醒目,吸引眼球,这些在普通海报上用PS没事情,因为这样的海报小,放大不会影响效果,但是转换成大些的海报就不行了,PS放大到一定的程度会模糊失真(当然客户的主题商品一般不会,因为客户的商品照片全是

hbase 利用rowkey设计进行多条件查询

摘要 本文主要内容是通过合理Hbase 行键(rowkey)设计实现快速的多条件查询,所采用的方法将所有要用于查询中的列经过一些处理后存储在rowkey中,查询时通过rowkey进行查询,提高rowkey的利用率,加快查询速度.行键(rowkey)并不是简单的把所有要查询的列的值直接拼接起来,而是将各个列的数据转成整型(int)数据来存储.之后实现两个自定义的比较器(comparator):一个是相等比较器,用于实现类似于SQL的多条件精确查找功能. select * from table wh

利用jQuery设计横/纵向菜单

在网页中,菜单扮演着"指路者"的角色.怎样设计一个人性化的菜单呢.以下小编带着大家一起做. 效果图: 设计历程: 1.首先利用html中的<ul>和<li>标签进行嵌套,搭起一个总体的框架.例如以下图所看到的: Html代码: <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title&

c# 利用AForge和百度AI开发实时人脸识别

baiduAIFaceIdentify项目是C#语言,集成百度AI的SDK利用AForge开发的实时人脸识别的小demo,里边包含了人脸检测识别,人脸注册,人脸登录等功能 人脸实时检测识别功能 思路是利用AForge打开摄像头,通过摄像头获取到的图像显示在winform窗体中AForge的控件中,利用AForge控件中的NewFrame事件获取要显示的每一帧的图像,获取图像传输到百度AI平台进行人脸检测,并且将检测结果反馈到界面显示的图像中.在这个过程中有两个问题,获取图像上传到百度AI平台进行

UE4笔记:利用Widget设计一个切换材质功能

UE4引擎中的Widget蓝图是一个重要的工具,可用于场景中的页面叠加,镜头绑定,场景切换等多处地方,在这里笔者介绍一种利用控件蓝图和场景中物体进行信息交互的方法,直观的体现就是进行物体的材质切换. 1.创建控件蓝图 控件蓝图不同于一般的逻辑蓝图,主要表现在其需要进行画面的设计和平铺.在内容浏览器中创建一个控件蓝图,命名为SwitchMat_UI 双击打开控件蓝图编辑器,进行页面的设计布局. 拖放一个水平盒子到页面中,位置和大小如下图所示(可根据个人喜好进行布局),命名为SwitchMat,同时