第一印象
ASP(回答集编程)是基于逻辑程序和它们的回答集的声明式编程范式,它提供了一种简单且强大的建模语言来解决组合问题,而Potsdam Answer Set Solving Collection(Potassco)则把包括gringo、clasp的多种用于ASP的工具组合起来,成为一个集成的ASP系统clingo。
用途
主要用于快速解决计算困难的问题,如full-fledged SAT, MaxSAT, PB。集成于一个系统则可以让使用者更加关注实际的问题本身,而不是实现的方法。
初识语法
用一个例子直观地认识ASP的语法。汉诺塔问题由3根柱子和4个盘子组成,初始状态和目标状态如图1所示。每次能且只能移动一个位于最顶层的盘子,且编号小的盘子不能放在编号大的盘子上面。
图1 汉诺塔问题的初始状态和目标状态
于是问题可以抽象为,给定一个初始状态、一个目标状态、一个数字n,判断是否存在一个移动序列满足在n步之内从初始状态到目标状态。在ASP中,我们通常给出一个问题的正规定义,分别对实例和编码(应用到每一个实例)详细说明。
问题实例
问题涉及以下谓词:
- peg/1:描述柱子。/后面的数字表示接收参数的个数。
- disk/1:描述盘子。
- init_on/2:描述初始状态。
- goal_on/2:描述目标状态。
- moves/1:描述在多少步以内必须到达目标状态。
当最多允许15步时,图1中的汉诺塔问题实例可由图2中的事实描述。
图2
语法糖:第1行的“;”,可以扩展为peg(a).,peg(b).,peg(c).。第2行的“..”,指一个区间,即1,2,3,4。
问题编码
我们通过描述一些包含着独立于某一实例的变量的规则,来对汉诺塔问题进行编码。逻辑上把编码阶段分为四部分:Generate, Define, Test, Display。如图3所示。
图3
变量的含义:
- D:表示盘子
- P:表示柱子
- T:某次移动的序号,某个时间点
- M:移动的总长度
Generate部分包含了一条规则,其含义为在某个时间点T,有且只有一次把盘子D移到柱子P的操作能被执行。规则的头部(即:-的左边部分)由一组文字和guard(“=1”)组成,文字用“:”后面的条件来扩展。头部被称为基数约束,当真元素的数量等于guard说明的那样(即为1),基数约束满足。
在规则的体(:-的右边部分)定义了移动序号T从1递增到M。在Generate部分我们仍未定义编号小的盘子不能放在编号大的盘子上面的规则。
Define部分包含了辅助性的谓词。以下是4-9行中每条规则的含义:
- 把一次移动投影到盘子D和时间点T上。也就是说,当目标柱子P可忽略时,可以用move(D,T)代替move(D,P,T)
- 谓词on描述了某个时间点中的一个状态。初始状态中,若D在P上,则on(D,P,0)成立