本文介绍的是基于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-地图路径寻路的更多相关文章

  1. 【比较】遗传算法GA和遗传编程GP有什么不同?

    遗传算法GA 本质上有一个固定的长度,这意味着所产生的功能有限的复杂性 通常会产生无效状态,因此需要以非破坏性方式处理这些状态 通常依赖于运算符优先级(例如,在我们的例子中,乘法发生在减法之前),这可 ...

  2. 第四届58topcoder编程大赛--地图路径规划

    layout: post title: 第四届58topcoder编程大赛 subtitle: 58ACM catalog: true tags: - A* 算法 - C++ - 程序设计 问题及背景 ...

  3. 【Python Deap库】遗传算法/遗传编程 进化算法基于python DEAP库深度解析讲解

    目录 前言 概述 启发式的理解(重点) 优化问题的定义 个体编码 初始族群的创建 评价 配种选择 锦标赛 轮盘赌选择 随机普遍抽样选择 变异 单点交叉 两点交叉 均匀交叉 部分匹配交叉 突变 高斯突变 ...

  4. 遗传编程(GA,genetic programming)算法初探,以及用遗传编程自动生成符合题解的正则表达式的实践

    1. 遗传编程简介 0x1:什么是遗传编程算法,和传统机器学习算法有什么区别 传统上,我们接触的机器学习算法,都是被设计为解决某一个某一类问题的确定性算法.对于这些机器学习算法来说,唯一的灵活性体现在 ...

  5. 【遗传编程/基因规划】Genetic Programming

    目录 背景介绍 程序表示 初始化 (Initialization) Depth定义 Grow方法 Full方法 Ramped half-and-half方法 适应度(Fitness)与选择(Selec ...

  6. 【python(deap库)实现】GEAP 遗传算法/遗传编程 genetic programming +

    目录 前言 1.优化问题的定义 单目标优化 多目标优化 2.个体编码 实数编码 二进制编码 序列编码(Permutation encoding) 粒子(Particles) 3 初始种群建立 一般族群 ...

  7. Android中Google地图路径导航,使用mapfragment地图上画出线路(google map api v2)详解

    在这篇里我们只聊怎么在android中google map api v2地图上画出路径导航,用mapfragment而不是mapview,至于怎么去申请key,manifest.xml中加入的权限,系 ...

  8. iOS百度地图路径规划和POI检索详细总结-b

    路径规划.png 百度地图的使用 百度地图API的导入网上说了许多坑,不过我遇到的比较少,这里就放两个比较常见的吧.坑一: 奥联WIFI_xcodeproj.png 如上图所示,在infoplist里 ...

  9. Vue 高德地图 路径规划 画点

    CDN 方式 <!--引入高德地图JSAPI --> <script src="//webapi.amap.com/maps?v=1.4.13&key=您申请的ke ...

随机推荐

  1. Linux 内核 低级 sysfs 操作

    kobject 是在 sysfs 虚拟文件系统之后的机制. 对每个在 sysfs 中发现的目录, 有一个 kobject 潜伏在内核某处. 每个感兴趣的 kobject 也输出一个或多个属性, 它出现 ...

  2. LuoguP1402 酒店之王

    LuoguP1402 酒店之王 最大流题目.带有一定的思维技(tao)巧(lu) 依旧分析题目.如果只有房间或者菜一种限制.那么就是一道裸的最大流了 可是两种条件都应当满足, 这貌似也可以做. 因为每 ...

  3. Delta Lake基础操作和原理

    目录 Delta Lake 特性 maven依赖 使用aws s3文件系统快速启动 基础表操作 merge操作 delta lake更改现有数据的具体过程 delta表schema 事务日志 delt ...

  4. SQLite3的使用(封装很长,直接使用sqlite3_open函数,LIBS += sqlite3.dll 即可)good

    1.下载sqlite3相关文件sqlite3.dll.sqlite3.h(可从http://download.csdn.net/detail/mingxia_sui/5249070下载),添加到工程的 ...

  5. 超简单!pytorch入门教程(三):构造一个小型CNN

    torch.nn只接受mini-batch的输入,也就是说我们输入的时候是必须是好几张图片同时输入. 例如:nn. Conv2d 允许输入4维的Tensor:n个样本 x n个色彩频道 x 高度 x ...

  6. vue学习笔记(二)vue的生命周期和钩子函数

    前言 通过上一章的学习,我们已经初步的了解了vue到底是什么东西,可以干什么,而这一篇博客主要介绍vue的生命周期和它常用的钩子函数,如果有学过java的园友可能有接触到在学习servlet的时候学过 ...

  7. Java提供的JDBC标准- 六大步骤

    JDBC 1.//加载驱动 class.forname 2.//创建连接connection 3.//创建 管道流 statement或  preparestatement预处理4.//执行sql语句 ...

  8. python版飞机大战代码简易版

    # -*- coding:utf-8 -*- import pygame import sys from pygame.locals import * from pygame.font import ...

  9. spark(1.1) mllib 源码分析(三)-决策树

    本文主要以mllib 1.1版本为基础,分析决策树的基本原理与源码 一.基本原理 二.源码分析 1.决策树构造 指定决策树训练数据集与策略(Strategy)通过train函数就能得到决策树模型Dec ...

  10. 14.python案例:爬取电影天堂中所有电视剧信息

    1.python案例:爬取电影天堂中所有电视剧信息 #!/usr/bin/env python3 # -*- coding: UTF-8 -*- '''======================== ...