java fushubaioshi_java – AI如何为战列舰建立遗传规划模型

回答第一部分:遗传算法的基础是拥有一组演员,其中一些演员重现.选择适者进行繁殖,后代是略有变异的父母的副本.这是一个非常简单的概念,但要编程它,你必须有可以随机选择和动态修改的动作.对于战舰模拟我创建了一个叫做射手的类,因为它在某个位置“射击”.这里的假设是第一个位置被击中,射手现在正试图沉没战列舰.

public class Shooter implements Comparable {

private static final int NUM_SHOTS = 100;

private List shots;

private int score;

// Make a new set of random shots.

public Shooter newShots() {

shots = new ArrayList(NUM_SHOTS);

for (int i = 0; i < NUM_SHOTS; ++i) {

shots.add(newShot());

}

return this;

}

// Test this shooter against a ship

public void testShooter(Ship ship) {

score = shots.size();

int hits = 0;

for (Position shot : shots) {

if (ship.madeHit(shot)) {

if (++hits >= ship.getSize())

return;

} else {

score = score - 1;

}

}

}

// get the score of the testShotr operation

public int getScore() {

return score;

}

// compare this shooter to other shooters.

@Override

public int compareTo(Shooter o) {

return score - o.score;

}

// getter

public List getShots() {

return shots;

}

// reproduce this shooter

public Shooter reproduce() {

Shooter offspring = new Shooter();

offspring.mutate(shots);

return offspring;

}

// mutate this shooter's offspring

private void mutate(List pShots) {

// copy parent's shots (okay for shallow)

shots = new ArrayList(pShots);

// 10% new mutations, in random locations

for (int i = 0; i < NUM_SHOTS / 10; i++) {

int loc = (int) (Math.random() * 100);

shots.set(loc, newShot());

}

}

// make a new random move

private Position newShot() {

return new Position(((int) (Math.random() * 6)) - 3, ((int) (Math.random() * 6)) - 3);

}

}

这里的想法是射手有多达100次射击,随机选择在X中的-3和Y中的-3之间.是的,100次射击是过度的,但是嘿,无论如何.将一艘船发送到这个Shooter.testShooter,它将得分,100分是最好的分数,0分是最差的.

这个射手演员有重现和变异的方法,将返回一个后代,其中10%的镜头随机变异.一般的想法是,最好的射手已经“学会”尽快以交叉模式(”)射击,因为一艘船以四种方式之一(北,南,东,西)定向.

运行模拟的程序ShooterSimulation非常简单:

public class ShooterSimulation {

private int NUM_GENERATIONS = 1000;

private int NUM_SHOOTERS = 20;

private int NUM_SHOOTERS_NEXT_GENERATION = NUM_SHOOTERS / 10;

List shooters = new ArrayList(NUM_SHOOTERS);

Ship ship;

public static void main(String... args) {

new ShooterSimulation().run();

}

// do the work

private void run() {

firstGeneration();

ship = new Ship();

for (int gen = 0; gen < NUM_GENERATIONS; ++gen) {

ship.newOrientation();

testShooters();

Collections.sort(shooters);

printAverageScore(gen, shooters);

nextGeneration();

}

}

// make the first generation

private void firstGeneration() {

for (int i = 0; i < NUM_SHOOTERS; ++i) {

shooters.add(new Shooter().newShots());

}

}

// test all the shooters

private void testShooters() {

for (int mIdx = 0; mIdx < NUM_SHOOTERS; ++mIdx) {

shooters.get(mIdx).testShooter(ship);

}

}

// print the average score of all the shooters

private void printAverageScore(int gen, List shooters) {

int total = 0;

for (int i = 0, j = shooters.size(); i < j; ++i) {

total = total + shooters.get(i).getScore();

}

System.out.println(gen + " " + total / shooters.size());

}

// throw away the a tenth of old generation

// replace with offspring of the best fit

private void nextGeneration() {

for (int l = 0; l < NUM_SHOOTERS_NEXT_GENERATION; ++l) {

shooters.set(l, shooters.get(NUM_SHOOTERS - l - 1).reproduce());

}

}

}

代码从run方法读取为伪代码:make firstGeneration然后迭代多代.对于每一代,为ship设置newOrientation,然后执行testShooters,并使用Collections.sort对测试结果进行排序. printAverageScore的测试,然后构建nextGeneration.用你可以的平均分数列表,咳嗽咳嗽,做一个’分析’.

结果图如下所示:

UdGV7.png

正如你所看到的那样,平均得分相当低,但学得很快.但是,船的方向不断变化,除随机分量外还会产生一些噪音.一次又一次的突变使得这个群体变得有点混乱,但随着整个群体的改善而变得越来越少.

挑战,以及许多论文确定的原因,是使更多的事情变得可变,特别是以建设性的方式.例如,镜头数量可能是可变的.或者,用根据最后一次击中是击中还是未命中而树枝的树替换击球列表可能会改善一些事情,但很难说.这就是’决策’逻辑考虑因素的来源.有一个随机镜头列表或树根据先前的镜头决定采取哪个分支更好吗?更高层次的挑战包括预测哪些变化将使小组学得更快,并且不易受到不良突变的影响.

最后,考虑可能有多个团体,一组是战列舰猎人,另一组是潜艇猎人.每个组虽然由相同的代码组成,但可以“发展”不同的内部“遗传学”,使他们能够专注于他们的任务.

无论如何,一如既往,从一个简单的地方开始,随时学习,直到你变得足够好回去阅读论文.

PS>也需要这个:

public class Position {

int x;

int y;

Position(int x, int y ) {this.x=x; this.y=y;}

@Override

public boolean equals(Object m) {

return (((Position)m).x==x && ((Position)m).y==y);

}

}

UDATE:添加了Ship类,修复了一些错误:

public class Ship {

List positions;

// test if a hit was made

public boolean madeHit(Position shot) {

for (Position p: positions) {

if ( p.equals(shot)) return true;

}

return false;

}

// make a new orientation

public int newOrientation() {

positions = new ArrayList(3);

// make a random ship direction.

int shipInX=0, oShipInX=0 , shipInY=0, oShipInY=0;

int orient = (int) (Math.random() * 4);

if( orient == 0 ) {

oShipInX = 1;

shipInX = (int)(Math.random()*3)-3;

}

else if ( orient == 1 ) {

oShipInX = -1;

shipInX = (int)(Math.random()*3);

}

else if ( orient == 2 ) {

oShipInY = 1;

shipInY = (int)(Math.random()*3)-3;

}

else if ( orient == 3 ) {

oShipInY = -1;

shipInY = (int)(Math.random()*3);

}

// make the positions of the ship

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

positions.add(new Position(shipInX, shipInY));

if (orient == 2 || orient == 3)

shipInY = shipInY + oShipInY;

else

shipInX = shipInX + oShipInX;

}

return orient;

}

public int getSize() {

return positions.size();

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值