【问题标题】:Call prolog predicate from python从python调用prolog谓词
【发布时间】:2011-05-23 21:49:01
【问题描述】:

我有一些 .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
[1, 2, 3, 4, 5]

ps:这只是一个例子,我不想重写我当前的 Prolog 程序。

【问题讨论】:

    标签: python prolog ffi swi-prolog


    【解决方案1】:

    并不是我有直接的经验,而是有一个名为PySWIP 的项目提供了 Python 和 SWI-Prolog 之间的桥梁。托管在 Google Code 项目页面上的 wiki 包含 installation instructions 和一些 usage examples

    编辑(2019 年 7 月 5 日)

    PySWIP 现在似乎在Github 上维护,并拥有自己的installation instructions。 TLDR:安装 SWI-Prolog 和 pip install pyswip 应该可以完成 Python 2 和 3 的工作。

    【讨论】:

      【解决方案2】:

      由于您不想“重写我当前的 Prolog 程序”,我认为自然的方法是从 Python 对 SWI-Prolog 进行外部调用,并传递适当的命令行参数。

      看看这个 SO 讨论,How to call external command in Python,从 2008 年 9 月开始。使用subprocess 模块允许将来自外部命令的标准输出通过管道传输到 Python 进程并在那里作为流读取。

      这减少了为 SWI-Prolog 选择 command line arguments 的问题。可以通过类 Unix 系统上的 shell 脚本或 Windows 上的“DOS”批处理/cmd 文件间接调用 SWI-Prolog,但我将不再提及这种间接调用。

      请参阅第 2 节中的讨论。 -g-t 选项的 SWI-Prolog 手册(上面链接)的 2.4.2。例如:

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

      可能会做你想做的事。 --quiet 选项禁止显示横幅/欢迎消息,您可能希望简化对 Python 接收到的输出的解析。

      【讨论】:

      • 是的,它是一种变体。但不是很实用
      • @garm0nboz1a:如果有需要澄清的具体步骤,我很乐意尝试。该方法将 SWI-Prolog 程序视为“黑匣子”。因此,虽然现有的 .pl 编码对 Python 调用者“一无所知”,但这样的调用者必须承担解析 Prolog 顶级查询结果并对其进行适当处理的负担,例如赋值给一个变量。您的示例不清楚是否需要 Python 代码来“识别”result 的数据类型,或者只是将所有值视为字符串。因此,您的问题有很多(我)未探索的方面。
      【解决方案3】:

      Python3 的更新,在撰写本文时 PyPI 中的 PySwip 仅适用于旧版 Python,但 source code on github 与 Python3 兼容。你可以 git clone 这个,运行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]}
      

      【讨论】:

      • 似乎可以从 pypi 再次为 Python 3 安装
      【解决方案4】:
      from subprocess import Popen, PIPE, STDOUT
      
      p = Popen('/usr/local/sicstus4.2.3/bin/sicstus', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
      cmd = open('/path/to/your/test.pl').read()
      res = p.communicate(cmd)
      for line in res:
          print line
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多