从Python调用Prolog谓词

6 投票
4 回答
8266 浏览
提问于 2025-04-16 18:12

我有一个 .pl 文件,我想从 Python 脚本中调用里面声明的谓词(也就是函数)。我该怎么做呢?

比如说,我有一个文件叫 test.pl

rD( [], Ans, Ans ).
rD( [X|Xs], Ans, Acc ) :-
    member( X, Acc ),
    rD( Xs, Ans, Acc ), !.
rD( [X|Xs], Ans, Acc ) :-
    \+member( X, Acc ),
    append( Acc, [X], AccNew ),
    rD( Xs, Ans, AccNew ), !.

它的工作方式是:

?- rD( [1,2,3,4,5,4], X ).
X = [1, 2, 3, 4, 5].

我想从 Python 脚本中以某种方式调用 rD,并把结果放到一个叫做 result 的变量里。

result
[1, 2, 3, 4, 5]

补充说明:这只是一个例子,我不想重写我现在的 Prolog 程序。

4 个回答

2

目前在写这段话时,Python3的PySwip更新在PyPI上只适用于旧版Python,但你可以去GitHub上的源代码,那里有兼容Python3的版本。你可以用git克隆这个代码库,然后运行 python3 setup.py install,这样就能安装Python3版本了。

如果你想查看一个已经存在的知识库,假设它的文件名是knowledge_base.pl:

from pyswip import Prolog
prolog = Prolog()
prolog.consult("knowledge_base.pl")
for res in prolog.query("rD( [1,2,3,4,5,4], X )."):
    print(res)

# output:
# {'X': [1, 2, 3, 4, 5]}
4

既然你不想“重写我现在的Prolog程序”,那么一个自然的做法就是从Python中调用SWI-Prolog,并传递合适的命令行参数。

你可以看看这个讨论,如何在Python中调用外部命令,这是2008年9月的内容。使用subprocess模块可以让外部命令的输出直接传给Python程序,并在那儿作为流来读取。

这样一来,问题就变成了选择SWI-Prolog的命令行参数。你可以通过在类Unix系统上使用shell脚本,或者在Windows上使用“DOS”批处理文件来间接调用SWI-Prolog,但我就不再详细说这种间接调用了。

特别要注意SWI-Prolog手册中第2.4.2节的讨论(上面有链接),关于-g-t选项。例如:

swipl --quiet -t rD( [1,2,3,4,5,4], X ),halt

这可能正是你想要的。--quiet选项可以抑制欢迎信息,这样你在解析Python接收到的输出时会更简单。

5

虽然我没有直接的经验,但有一个项目叫做 PySWIP,它可以让Python和SWI-Prolog之间进行连接。这个项目在Google Code的页面上有一个维基,里面包含了安装说明和一些使用示例

编辑(2019年7月5日)

现在PySWIP似乎在Github上得到了维护,并且有自己的安装说明。简单来说:安装SWI-Prolog,然后运行 pip install pyswip 就可以了,适用于Python 2和3。

撰写回答