5

I have some .pl file and I want to call predicate declared in it from python script. How can I do that?

For example, 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 ), !.

Working like

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

I want to call rD somehow from python script and get answer in result variable

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

ps: it is just an example, and I don't want to rewrite my current Prolog program.

false
  • 10,182
  • 12
  • 93
  • 182

4 Answers4

3

Not that I have a direct experience with it, but there is a project called PySWIP that provides a bridge between Python and SWI-Prolog. The wiki hosted on Google Code's project pages holds installation instructions and some usage examples.

EDIT (5th of July 2019)

PySWIP now seems to be maintained on Github, with its own installation instructions. TLDR: installing SWI-Prolog and pip install pyswip should do the job, for both Python 2 and 3.

Martin
  • 817
  • 6
  • 14
Giulio Piancastelli
  • 13,500
  • 5
  • 38
  • 59
3

Since you don't want to "rewrite my current Prolog program," I think the natural approach is to make an external call from Python to SWI-Prolog, passing appropriate command line arguments.

Take a look at this SO discussion, How to call external command in Python, from Sept. 2008. Using the subprocess module allows the stdout from an external command to be piped to the Python process and read as a stream there.

This reduces the problem to choosing command line arguments for SWI-Prolog. It is possible to invoke SWI-Prolog indirectly, through a shell-script on Unix-like systems or a "DOS" batch/cmd file on Windows, but I'll omit further mention of such an indirect call.

See especially the discussion in Sec. 2.4.2 of the SWI-Prolog manual (linked above) of -g and -t options. For example:

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

will likely do what you want. The --quiet option suppresses the banner/welcome message, which you probably want to simplify parsing the output as received by Python.

Community
  • 1
  • 1
hardmath
  • 8,423
  • 2
  • 32
  • 60
  • Yeah, it is sort of variant. But not really usable – ДМИТРИЙ МАЛИКОВ May 25 '11 at 15:41
  • @garm0nboz1a: If there are specific steps that need clarification, I'd be happy to try. The approach would treat an SWI-Prolog program as a "black box". Thus while the existing .pl coding "knows" nothing about the Python caller, such a caller must assume the burden of parsing the Prolog top-level query result and doing something appropriate with it, e.g. assigning to a variable. Your example is not clear about whether Python code is required to "recognize" the data type of `result` or just treat all values as strings. So there are many unexplored (by me) aspects to your question. – hardmath May 26 '11 at 14:12
1

An update for Python3, PySwip in PyPI at the time of writing is for legacy Python only, but the source code on github is Python3 compatible. You can git clone this, run python3 setup.py install and it'll give you a Python3 version.

To consult an existing knowledge base, stored as 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]}
Paul Brown
  • 1,835
  • 10
  • 17
-1
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
ScotchAndSoda
  • 2,573
  • 2
  • 30
  • 37