ASP 是什么?
ASP 的全称是 Answer Set Programming,中文翻译为问答集编程。对于它的解释,有这么几个要点。
第一,它属于声明式编程的一种。声明式编程,简而言之就是告诉计算机你想“做什么”,而不是“怎么做”。SQL 是很多人都熟悉的声明式编程的例子。如果要从一个数字集合里找出所有小于10 的数字,怎么做? - select * from tab where val < 10
复制代码
但如果是命令式编程,怎么做? - List result;
- for i in collection {
- if (i < 10) {
- result.add(i);
- }
- }
复制代码
不要纠结语法,重点关注一下表达方式的区别。
第二,它主要是针对复杂的搜索问题。搜索问题可能是从一些存储在数据结构中的数据里获取一些信息,也可能是计算满足某一问题约束所有可能的结果。前者比如说上面提到数据检索问题,后者比如说最短路径问题。
第三,它是基于稳定模型语义的逻辑编程。逻辑编程通常是指用一组逻辑语言(符号)来描述关于某个问题的事实和规则。而稳定模型语义是一个挺复杂的东西,可以看看这篇文章的介绍。这里面涉及到一个概念叫做失败即否定(negation as failure )。我认为,它的意思就是,基于当前的事实和规则推断失败的,即为否定。当然,由于事实可能并不全面,在增加事实之后,结果可能不是否定的。这就又涉及到 “非单调推理” 的问题了,前面提到的博客里面有所涉及。
一些参考概念: 编程范式 ASP 搜索问题 稳定模型语义
如何运行 ASP 程序
波茨坦大学开发了一个程序集,叫做 Potassco(Potsdam Answer Set Solving Collection)。其中的 clingo 可以用来运行 ASP 程序。
clingo 中有两个子程序:
- gringo 用来翻译用户写的逻辑程序
- clasp 用来求解
在官方网站上,有非常详细的文档介绍 Potassco,有兴趣的读者可以去参考。一般来讲,运行一个 ASP 程序就像下面这样一条命令:
其中的 .lp 文件就包含了 ASP 代码。
在这里可以下载 clingo,在本地解压之后,目录下就有可执行程序了。
如何编写 ASP 程序
在 Potassco 的文档里,有详细的语法说明。如果有时间,建议好好看看。我这里就简单的说一下思路。
一个简单的 ASP 程序可能包含三个部分:
其中事实和规则部分,用来描述问题的。输出部分,用来查看结果。所以,前者是最重要的。整个 ASP 程序的核心目的就是:把问题描述清楚了,自然就能得到正确的结果。而 gringo 也提供了不少的语法符号,来帮助我们做到这一点。后面的章节我会拿出一个小例子来作说明。这篇博客 也介绍了很多基础知识。
一个实例
- % fact
- p(1..4).
- e(1, (3;4)).
- e(2, 4).
- e(3, (1;4)).
- e(4, (1;2;3)).
- % rule
- c(X, Y) :- p(X), p(Y), not e(X, Y), X != Y.
- % Display
- #show c/2.
复制代码
上面是一个非常简单的例子,仅供参考。我们来求图中没有边直接相连的点。
前 5 行代码是事实部分,它如实描述了 图1 的情况。p 表示点,e 表示边。p(1…4) 这种写法等同 p(1). p(2). p(3). p(4). 。其中 “.” 是一句代码的结束符。e(1, (3;4)). 等同于 e(1, 3). e(1, 4),表示 1 到 3、4 有边。1…4 和 “;” 都是语法糖。
所以,事实部分就是在说,有 4 个点,并且他们之间有的有边,有的没有。
第 6 行代码是规则部分。“:-” 我们可以理解为:“如果它后面的条件成立,那么前面就成立”。而 “,” 则表示“并且”的意思。“not” 顾名思义,表示否定。所以 c(X, Y) 成立的条件就是:“有两个点 X 和 Y,他们之间没有边,并且 X,Y 不是同一个点。”
这样,我们发现,c(X, Y) 实际上就是要求的结果。所以,在最后一行输出了 c。这里 #show 表示输出,c/2 中的 c 表示 c(X, Y),而 2 则表示 c 有两个元素。
这个程序的执行命令如下:
后面的 “-n 10” 表示输出多少个解。有时候,程序可能有不止一个解。但我们的程序只有一个解,下面是输出结果: - clingo version 5.3.0
- Reading from test
- Solving...
- Answer: 1
- c(2,1) c(1,2) c(3,2) c(2,3)
- SATISFIABLE
- Models : 1
- Calls : 1
- Time : 0.001s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
- CPU Time : 0.001s
复制代码
上面的 c(2,1) c(1,2) c(3,2) c(2,3) 就是结果了。大家也可以思考一下,怎么能够让 c(2,1) 和 c(1,2) 只保留一个呢?
参考资料
资料1 资料2 资料3 资料4
来源:https://blog.csdn.net/weixin_43162745/article/details/84167137 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |