遗传编程GP-地图路径寻路
本文介绍的是基于GP,并非A*算法,算是另类实现吧。
先看看地图定义,在文本文件中定义如下字符串,代表30列11行大小的地图
初始位置在左上角(0,0) ,值为1的是允许走的通的路,目标位置为右下角(29,10)
1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
算法运行效果如下:
"C:\Program Files\Java\jdk1.8.0_211\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.2\lib\idea_rt.jar=54171:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_211\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\rt.jar;C:\Research-Code\demo1\target\classes;C:\Users\McKay\.m2\repository\io\jenetics\jenetics\5.1.0\jenetics-5.1.0.jar;C:\Users\McKay\.m2\repository\io\jenetics\jenetics.ext\5.1.0\jenetics.ext-5.1.0.jar;C:\Users\McKay\.m2\repository\io\jenetics\jenetics.prog\5.1.0\jenetics.prog-5.1.0.jar;C:\Users\McKay\.m2\repository\commons-lang\commons-lang\2.6\commons-lang-2.6.jar" MapGame.GameDemo
1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
G: 15769
--------------------
map-->Right-->Right-->Right-->Right-->Right-->Down-->Down-->Down-->Left-->Down-->Down-->Left-->Down-->Down-->Right-->Right-->Right-->Right-->Right-->Down-->Down-->Down-->Right-->Right-->Right-->Right-->Right-->Right-->Right-->Right-->Right-->Right-->
E: 1320.0 Process finished with exit code 0
这边由于是套遗传编程,因此会定义几个固定操作算子:上移、下移、左移、右移;看看上移算子代码:
public class GoUpOp implements Op<TempMapInfo> {
private MapController mapController; //地图控制工具类,比如判断能否移动到某个坐标、是否完成地图等
public GoUpOp(MapController mapController) {
this.mapController=mapController;
} @Override
public String name() {
return "Up";
} @Override
public int arity() {
return 1;
} @Override
public String toString() {
return "Up";
} @Override
public TempMapInfo apply(TempMapInfo[] tempMapInfos) {
TempMapInfo newInfo=tempMapInfos[0].cloneMe(); //需要深度克隆,防止多线程对象直接互相影响 if(newInfo.currentLocationY==0)
{
newInfo.score-=1000; //已经在最上方了,不能再做上移动作了
newInfo.tag+="-UP"; //惩罚分,扣除1000分
return newInfo;
}
if(!mapController.canMove2(newInfo.currentLocationX, newInfo.currentLocationY-1)) //是否上移位置是路
{
newInfo.score-=1000; //惩罚扣除1000分
newInfo.tag+="-UP";
return newInfo;
} newInfo.score+=10; //可以走,奖励10分
newInfo.currentLocationY--; //递减y坐标
if(newInfo.visited.contains(newInfo.currentLocationX+","+newInfo.currentLocationY)) //不能重复访问点
newInfo.score-=1000;
else
newInfo.visited.add(newInfo.currentLocationX+","+newInfo.currentLocationY); if(mapController.isSuccess(newInfo.currentLocationX, newInfo.currentLocationY)) //判断是否地图完成
newInfo.score+=1000;
newInfo.tag+="-UP";
return newInfo;
} }
下面需要将这些操作算子嵌进GP中:
public static void main(String[] args) { Integer[][] map=GetMap();
dispalyMap(map); TempMapInfo mapInfo=new TempMapInfo();
mapInfo.score=0;
mapInfo.currentLocationX=0;
mapInfo.currentLocationY=0; //左上角为起点 List<Op<TempMapInfo>> terminals=new ArrayList<>();
terminals.add(Const.of("map", mapInfo)); MapController mapController=new MapController(map); final ISeq<Op<TempMapInfo>> TMS = ISeq.of(terminals);
final ISeq<Op<TempMapInfo>> OPS = ISeq.of(new GoLeftOp(mapController), new GoRightOp(mapController), new GoUpOp(mapController), new GoDownOp(mapController));
final GameSearcher gameSearcher = GameSearcher.of(
GameSearcher.codecOf(
OPS, TMS, 20,
t -> t.getGene().size() < 60
)
); final Engine<ProgramGene<TempMapInfo>, Double> engine = Engine
.builder(gameSearcher)
.populationSize(500)
.maximizing()
.alterers(
new SingleNodeCrossover<>(0.1),
new Mutator<>(0.3),
new UniformCrossover<>(0.5)
)
.offspringSelector(new TournamentSelector<>(2))
.survivorsSelector(new TournamentSelector<>())
.build(); final EvolutionResult<ProgramGene<TempMapInfo>, Double> er =
engine.stream()
.limit(Limits.byExecutionTime(Duration.ofSeconds(60)))
.collect(EvolutionResult.toBestEvolutionResult()); final ProgramGene<TempMapInfo> program = er.getBestPhenotype()
.getGenotype()
.getGene(); final TreeNode<Op<TempMapInfo>> tree = program.toTreeNode();
System.out.println("G: " + er.getTotalGenerations());
printTree(tree.depthFirstStream().collect(Collectors.toList()));
System.out.println("E: " + gameSearcher._fitness(tree));
} private static void printTree(List<TreeNode<Op<TempMapInfo>>> lst) {
System.out.println("--------------------");
for(TreeNode<Op<TempMapInfo>> node:lst)
System.out.print(node.getValue()+"-->");
System.out.println();
}
上面的terminals变量是存放终结符的,此处是直接把操作动作放进去了,包含了分数、访问步骤、当前xy坐标等,只有1个变量
public class TempMapInfo {
public int currentLocationX;
public int currentLocationY;
public double score;
public List<String> visited=new ArrayList<>();
public String tag=""; public TempMapInfo()
{
visited.add("0,0");
} public TempMapInfo cloneMe()
{
TempMapInfo info=new TempMapInfo(); info.currentLocationX=this.currentLocationX;
info.currentLocationY=this.currentLocationY;
info.score=this.score;
info.tag=this.tag;
info.visited=new ArrayList<>();
for(String i:this.visited)
info.visited.add(i); return info;
}
}
GameSearcher是对GP算法的编码、解码封装、计算分值,算是核心:
public final class GameSearcher
implements Problem<Tree<Op<TempMapInfo>, ?>, ProgramGene<TempMapInfo>, Double>
{ private final Codec<Tree<Op<TempMapInfo>, ?>, ProgramGene<TempMapInfo>> _codec; private GameSearcher(
final Codec<Tree<Op<TempMapInfo>, ?>, ProgramGene<TempMapInfo>> codec
) {
_codec = requireNonNull(codec);
} @Override
public Function<Tree<Op<TempMapInfo>, ?>, Double> fitness() {
return this::_fitness;
} @Override
public Codec<Tree<Op<TempMapInfo>, ?>, ProgramGene<TempMapInfo>> codec() {
return _codec;
} public double _fitness(final Tree<Op<TempMapInfo>, ?> program) { List<TempMapInfo> lst=new ArrayList<>();
lst.add(new TempMapInfo()); List<TempMapInfo> results=lst.stream().map(args -> Program.eval(program, args)).collect(Collectors.toList()); double score=results.stream().mapToDouble(a->a.score).sum(); //这行是用来统计整个操作算子序列总得分用的,很重要
return score;
} public static GameSearcher of(
final Codec<Tree<Op<TempMapInfo>, ?>, ProgramGene<TempMapInfo>> codec
) {
return new GameSearcher(codec);
} public static Codec<Tree<Op<TempMapInfo>, ?>, ProgramGene<TempMapInfo>>
codecOf(
final ISeq<Op<TempMapInfo>> operations,
final ISeq<Op<TempMapInfo>> terminals,
final int depth,
final Predicate<? super ProgramChromosome<TempMapInfo>> validator
) {
if (depth > 200 || depth < 0) {
throw new IllegalArgumentException(format(
"Tree depth out of range [0, 30): %d", depth
));
} return Codec.of(
Genotype.of(ProgramChromosome.of(
depth,
validator,
operations,
terminals
)),
Genotype::getGene
);
}
}
算法介绍完毕,pom依赖如下:
<dependencies>
<!-- https://mvnrepository.com/artifact/io.jenetics/jenetics -->
<dependency>
<groupId>io.jenetics</groupId>
<artifactId>jenetics</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>io.jenetics</groupId>
<artifactId>jenetics.ext</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>io.jenetics</groupId>
<artifactId>jenetics.prog</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
遗传编程GP-地图路径寻路的更多相关文章
- 【比较】遗传算法GA和遗传编程GP有什么不同?
遗传算法GA 本质上有一个固定的长度,这意味着所产生的功能有限的复杂性 通常会产生无效状态,因此需要以非破坏性方式处理这些状态 通常依赖于运算符优先级(例如,在我们的例子中,乘法发生在减法之前),这可 ...
- 第四届58topcoder编程大赛--地图路径规划
layout: post title: 第四届58topcoder编程大赛 subtitle: 58ACM catalog: true tags: - A* 算法 - C++ - 程序设计 问题及背景 ...
- 【Python Deap库】遗传算法/遗传编程 进化算法基于python DEAP库深度解析讲解
目录 前言 概述 启发式的理解(重点) 优化问题的定义 个体编码 初始族群的创建 评价 配种选择 锦标赛 轮盘赌选择 随机普遍抽样选择 变异 单点交叉 两点交叉 均匀交叉 部分匹配交叉 突变 高斯突变 ...
- 遗传编程(GA,genetic programming)算法初探,以及用遗传编程自动生成符合题解的正则表达式的实践
1. 遗传编程简介 0x1:什么是遗传编程算法,和传统机器学习算法有什么区别 传统上,我们接触的机器学习算法,都是被设计为解决某一个某一类问题的确定性算法.对于这些机器学习算法来说,唯一的灵活性体现在 ...
- 【遗传编程/基因规划】Genetic Programming
目录 背景介绍 程序表示 初始化 (Initialization) Depth定义 Grow方法 Full方法 Ramped half-and-half方法 适应度(Fitness)与选择(Selec ...
- 【python(deap库)实现】GEAP 遗传算法/遗传编程 genetic programming +
目录 前言 1.优化问题的定义 单目标优化 多目标优化 2.个体编码 实数编码 二进制编码 序列编码(Permutation encoding) 粒子(Particles) 3 初始种群建立 一般族群 ...
- Android中Google地图路径导航,使用mapfragment地图上画出线路(google map api v2)详解
在这篇里我们只聊怎么在android中google map api v2地图上画出路径导航,用mapfragment而不是mapview,至于怎么去申请key,manifest.xml中加入的权限,系 ...
- iOS百度地图路径规划和POI检索详细总结-b
路径规划.png 百度地图的使用 百度地图API的导入网上说了许多坑,不过我遇到的比较少,这里就放两个比较常见的吧.坑一: 奥联WIFI_xcodeproj.png 如上图所示,在infoplist里 ...
- Vue 高德地图 路径规划 画点
CDN 方式 <!--引入高德地图JSAPI --> <script src="//webapi.amap.com/maps?v=1.4.13&key=您申请的ke ...
随机推荐
- Jmeter 发送json
阅读更多 使用jmeter发送json数据.方法有三种 原创,转载请注明出处 1.利用CSV Data set Config. 参考: http://demi-panda.com/2013/01/08 ...
- 2018百度之星资格赛A B F
A.调查问卷 度度熊为了完成毕业论文,需要收集一些数据来支撑他的论据,于是设计了一份包含 mm 个问题的调查问卷,每个问题只有 'A' 和 'B' 两种选项. 将问卷散发出去之后,度度熊收到了 nn ...
- RabbitMQ-工作原理
使用场景 在我们秒杀抢购商品的时候,系统会提醒我们稍等排队中,而不是像几年前一样页面卡死或报错给用户. 像这种排队结算就用到了消息队列机制,放入通道里面一个一个结算处理,而不是某个时间断突然涌入大批量 ...
- 移动端H5多页开发拍门砖经验
两年前刚接触移动端开发,刚开始比较疑惑,每次遇到问题都是到社区里提问或者吸取前辈的经验分享,感谢热衷于分享的开发者为前端社区带来欣欣向上的生命力.本文结合先前写的文章和开发经验分享给大家,希望也能帮助 ...
- openwrt上wifi探针的实现----mt7620a+rt2860v2
openwrt上wifi探针的实现----mt7620a+rt2860v2 [摘要:甚么是wifi探针 看到探针,感到很矮小上的模样,实在便是经过wifi汇集经由那个AP局限的脚机的mac地点,出有甚 ...
- Jquery xhr2跨域
相关享目托管在github: https://github.com/devgis/CSharpCodes
- vue文章学习路线
vue学习笔记(一)入门 Vue实现简单的购物车功能 vue学习笔记(二)vue的生命周期和钩子函数 使用webstorm搭建vue-cli项目 vue-cli项目中引入第三方插件 vue-cli项目 ...
- 009 Ceph RBD增量备份与恢复
一.RBD的导入导出介绍 Ceph存储可以利用快照做数据恢复,但是快照依赖于底层的存储系统没有被破坏 可以利用rbd的导入导出功能将快照导出备份 RBD导出功能可以基于快照实现增量导出 二.RBD导出 ...
- 从头学pytorch(九):模型构造
模型构造 nn.Module nn.Module是pytorch中提供的一个类,是所有神经网络模块的基类.我们自定义的模块要继承这个基类. import torch from torch import ...
- $loj\ 2031\ [SDOI2016]$数字配对 网络流
正解:网络流 解题报告: 我永远喜欢$loj$! 显然先预处理哪些$a$之间可以连边,然后考虑建两排点,连流量为$c_{i}\cdot c_{j}$,然后$ST$连$inf$,跑个费用流? 然后现在碰 ...