找回密码
 会员注册
查看: 113|回复: 0

ASP(Answer Set Programming)编程入门

[复制链接]

1389

主题

5

回帖

496万

积分

管理员

积分
4962990
发表于 2024-2-29 08:37:37 | 显示全部楼层 |阅读模式

ASP 是什么?


ASP 的全称是 Answer Set Programming,中文翻译为问答集编程。对于它的解释,有这么几个要点。

第一,它属于声明式编程的一种。声明式编程,简而言之就是告诉计算机你想“做什么”,而不是“怎么做”。SQL 是很多人都熟悉的声明式编程的例子。如果要从一个数字集合里找出所有小于10 的数字,怎么做?

  1. select * from tab where val < 10
复制代码

但如果是命令式编程,怎么做?

  1. List result;
  2. for i in collection {
  3. if (i < 10) {
  4. result.add(i);
  5. }
  6. }
复制代码

不要纠结语法,重点关注一下表达方式的区别。

第二,它主要是针对复杂的搜索问题。搜索问题可能是从一些存储在数据结构中的数据里获取一些信息,也可能是计算满足某一问题约束所有可能的结果。前者比如说上面提到数据检索问题,后者比如说最短路径问题。

第三,它是基于稳定模型语义的逻辑编程。逻辑编程通常是指用一组逻辑语言(符号)来描述关于某个问题的事实和规则。而稳定模型语义是一个挺复杂的东西,可以看看这篇文章的介绍。这里面涉及到一个概念叫做失败即否定(negation as failure )。我认为,它的意思就是,基于当前的事实和规则推断失败的,即为否定。当然,由于事实可能并不全面,在增加事实之后,结果可能不是否定的。这就又涉及到 “非单调推理” 的问题了,前面提到的博客里面有所涉及。

一些参考概念
编程范式
ASP
搜索问题
稳定模型语义

 

如何运行 ASP 程序


波茨坦大学开发了一个程序集,叫做 Potassco(Potsdam Answer Set Solving Collection)。其中的 clingo 可以用来运行 ASP 程序。

clingo 中有两个子程序:

  • gringo 用来翻译用户写的逻辑程序
  • clasp 用来求解

在官方网站上,有非常详细的文档介绍 Potassco,有兴趣的读者可以去参考。一般来讲,运行一个 ASP 程序就像下面这样一条命令:

  1. $ clingo files/crime.lp
复制代码

其中的 .lp 文件就包含了 ASP 代码。

在这里可以下载 clingo,在本地解压之后,目录下就有可执行程序了。

 

如何编写 ASP 程序


在 Potassco 的文档里,有详细的语法说明。如果有时间,建议好好看看。我这里就简单的说一下思路。

一个简单的 ASP 程序可能包含三个部分:

  • 事实
  • 规则
  • 输出

其中事实和规则部分,用来描述问题的。输出部分,用来查看结果。所以,前者是最重要的。整个 ASP 程序的核心目的就是:把问题描述清楚了,自然就能得到正确的结果。而 gringo 也提供了不少的语法符号,来帮助我们做到这一点。后面的章节我会拿出一个小例子来作说明。这篇博客 也介绍了很多基础知识。

 

一个实例


图1

  1. % fact
  2. p(1..4).
  3. e(1, (3;4)).
  4. e(2, 4).
  5. e(3, (1;4)).
  6. e(4, (1;2;3)).
  7. % rule
  8. c(X, Y) :- p(X), p(Y), not e(X, Y), X != Y.
  9. % Display
  10. #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 有两个元素。

这个程序的执行命令如下:

  1. ./clingo test -n 10
复制代码

后面的 “-n 10” 表示输出多少个解。有时候,程序可能有不止一个解。但我们的程序只有一个解,下面是输出结果:

  1. clingo version 5.3.0
  2. Reading from test
  3. Solving...
  4. Answer: 1
  5. c(2,1) c(1,2) c(3,2) c(2,3)
  6. SATISFIABLE
  7. Models : 1
  8. Calls : 1
  9. Time : 0.001s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
  10. 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
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?会员注册

×
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 11:40 , Processed in 0.355186 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表