基于ASP设计的走迷宫程序

基于ASP设计的走迷宫程序

  • ASP简介

ASP的全称为Answer Set Programming,其中文解释为回答集程序设计。ASP是逻辑程序设计的一个分支,ASP的基本思想是以逻辑程序的形式表达一个问题,是一种基于逻辑程序及其回答集的声明式编程范例。

  • 程序设计方法

生成-定义-测试方法(Generate-Define-Test methodology),GDT是ASP中编码搜索问题中的极为有效的方法。在GDT,一个程序可以将这个问题分为三部分组成:生成、定义和测试[9]。生成的作用是生成搜索空间(hypothesis generation)。由一组选择规则编码:

{A} ← B1,...,Bn, not C1,...,not Cm.

其中A、Bi和Ci是原子。规则规定,如果规则的主体所表达的条件成立,原子A可以是任意真或假。这个条件可能引用其他生成的谓词,或者引用定义的谓词。

定义部分是一些辅助谓词的一组定义。每个定义由一组规则:

A ← B1 ,..., Bn,not C1 ,..., not Cm.

其中,A、Bi、Cj是原子,A是被定义的辅助谓词。这些规则通常是以确定性的方式描述了如何从生成的谓词或其他定义的谓词中导出辅助谓词。

最后,测试部分消除生成的不满足期望约束的答案集。它们由约束规则表示:

←B1,...,Bn,not C1 ,..., not Cm.

这三种规则的集合将被称为GDT程序。GDT方式构思的ASP程序加强了内部结构丰富度。这三个部分中的每一个都可以由独立的组件组成。ASP程序中内部结构并不凸显,通常只有当我们研究谓词之间的依赖关系时才变得明显。这促使我们去定义一个逻辑,这个逻辑使GDT计划的内部结构变得更清晰。

  • 设计过程

运用ASP的GDT方法,可以对走迷宫问题进行编程设计,步骤如下:

1、生成

首先需要一个记录时间的原子(atom),以记录和限制代理移动的次数。发成部分主要生成代理在time(T)内在迷宫地图中所以的移动路径,也就是走迷宫问题的搜索空间,实现代码如下:

1 {valid_move((X,Y),T) :cell(X,Y) } 1 :- time(M),T=1..M.

其表示在时间T内,每个时间点有且只有一个代理在迷宫地图中移动。

在10*10的网格地图中,代理在其中移动一次就有COW * COL个可能移动的位置,所以其搜索空间大小为:

HG=(COW * COL)T

2、定义

需要定义代理每一个时间点的有效移动产生的效果,即当前时刻代理的位置将是当前时刻有效移动的目标格子。再者,需要定义这两者是迷宫中代理的移动方式,有以下两种:一是代理下一刻的有效移动是与代理相邻的格子,当然这个移动方向是随机的;二是当前时刻代理所处位置是传送隧道(link/2)的入口,下一刻代理将会到达隧道的另一端。实现代码如下:

agent_at(C,T) :-valid_move(C,T).

表示如果时间点T代理移动到座标为C的格子可以作为有效移动,那么在时间点T所处的位置为座标C。

agent_at(C,T+1) :- not valid_move(C,T+1),agent_at(C,T), time(T).

如果时间点T代理所处位置为座标C,T+1时未进行有效移动,且时间点T不是最后的时间点,那么在T+1代理所处的位置任为座标C。

adjacent((X, Y), (X + 1, Y)) :- cell((X, Y)), cell((X + 1, Y)).
adjacent((X + 1, Y), (X, Y)) :- cell((X, Y)), cell((X + 1, Y)).
adjacent((X, Y + 1), (X, Y)) :- cell((X, Y)), cell((X, Y + 1)).
adjacent((X, Y), (X, Y + 1)) :- cell((X, Y)), cell((X, Y + 1)).

表示随机选定一个格子,在上下左右四个方向与其相差一的座标点的格子的被称为相邻格子。

3、测试

要从数值如此庞大的搜索空间中找出为数不多的无冲突路径,如果采用穷举法,其中的计算量是无法想象的。所以测试部分主要目的是消除生成的不满足期望约束的答案集,重点就在于符合题设的选择规则。例如,不是相邻格子之间的移动不能当作有效移动;代理不能通过两个相邻之间有墙体的格子;代理所处位置不能是被锁住的格子;传送隧道是单向的,代理只能从规定的方向使用传送隧道。实现代码如下:

:- valid_move(C2, T),not adjacent(C1, C2), agent_at(C1, T-1).
:- valid_move(C2, T),wall(C1, C2) ,agent_at(C1, T-1). 
:- agent_at(C, T),remain_locked(C), time(M),T=1..M.
:- valid_move(C2, T), sup_adjacent (C1, C2) ,agent_at(C1, T-1).

以上为代理在迷宫地图中的行走规则,只能以相邻格子作为下一时间点的移动目标;两个格子之间存在墙体不能互相移动;代理不能移动到任被锁住的格子。

:-goal(X,Y),not agent_at((X,Y),T),time(T).

表示在最后时间点T,代理的位置并不在指定的目标位置,则被认定为目标没有完成。

当代理所处位置为传送隧道的入口时,有以下两种可能情况,一是代理可以选择不通过传送隧道,继续通往与其相邻的格子;二是代理必须通过传送隧道,没有其他选择。这两者在一个地图中可能都能实现,但这会导致代理从起始点到目标点的路径差异。所以就形成了两个版本,前者更适合找到最短路径和更具有灵活性,后者则体现题设规则的严谨。

下图显示第一种情况的代理移动方式的集合:

adjacent(C1, C2) :- link(C1, C2).

:- valid_move(C2, T),not adjacent(C1, C2), agent_at(C1, T-1).

版本一搜索空间

 

 

下图显示第二种情况代理移动方式的集合:

删除部分为link/2的补集,即全集adjacent/2不属于集合link/2的元素;

sup_adjacent/2  =  C(adjacent/2)( link/2)

其谓词定义和选择规则如下:

adjacent(C1, C2) :- link(C1, C2).

sup_adjacent (C1, C3) :- link(C1, C2),adjacent(C1, C3),C2!=C3.

:- valid_move(C2, T),not adjacent(C1, C2), agent_at(C1, T-1).

:- valid_move(C2, T), sup_adjacent (C1, C2) ,agent_at(C1, T-1).

 

版本二搜索空间

 

  • 结果展示

如下图所示,实际人工规划示例地图的完整路径:

 

自己画的路径
通过clingo编译器编译运行的结果
  •  小结

        ASP不算是一门通用编程语言,受众很小,算是一个用来求解受限的一阶逻辑问题的领域专用语言。领域专用语言最初发明出来就是为了快速解决基于约束的问题,类如类型推导、图着色、N皇后等问题和一些计算困难的组合问题。clingo一直在不断的更新中,不断的完善和研究新功能,在机器运算能力不再是阻碍程序性能的时候,依靠自身描述能力强,自动查找答案等独有性能特点,肯定会属于声明式编程的一片天地。

相关链接:

ASP在线编辑编译网站:https://potassco.org/clingo/run/

本地编译环境也可在此网站下载!

本文到此结束!!!!感谢阅读!!!!

注:本文章为博主原创,未经同意,禁止随意转载。内容如有错误,欢迎评论私信指正!!!

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章