Swiplserver: load existing prolog file into server

Based on my post on stackoverflow I also want to ask here. Is their a possibility on python with swiplserver to consult a file (like the consult command in the libary pyswip).

My setup based on the introductions of this forum is:

from swiplserver import PrologMQI, PrologThread
 with PrologMQI() as mqi:
     with mqi.create_thread() as prolog_thread:
         result = prolog_thread.query("member(X, [color(blue), color(red)])")
         print(result)

now I want to use the abilities I already have in some prolog file, call it prop.pl with example predicate

:-op(800, fx, ¬).
:-op(801, xfy, ∧).
:-op(802, xfy, ∨).
:-op(803, xfy, →).
:-op(804, xfy, ↔).
:-op(800, xfy, #).


m_Proposition_Binary_x_y(X ∨ Y, X, Y).
m_Proposition_Binary_x_y(X ∧ Y, X, Y).
m_Proposition_Binary_x_y(X → Y, X, Y).
m_Proposition_Binary_x_y(X ↔ Y, X, Y).

m_Proposition(X) :-
    m_Proposition_Atom(X).
m_Proposition(Binary) :-
    m_Proposition_Binary_x_y(Binary, X, Y),
    m_Proposition(X),
    m_Proposition(Y).
m_Proposition(¬ X) :-
    m_Proposition(X).



m_Proposition_Atom(p).
m_Proposition_Atom(q).

How can I load that file in my server, so I can use e.g. the query

result = intersection([A,(A→B)], [p, (p→q)], Aim).

I think a good approach to learning how to use swiplserver is to first figure out the right set of queries that work using the Prolog command line (i.e. the “top level”) and then convert that to Python.

For your example, on my macintosh I started with a basic consult but had issues:

?- consult("/Users/ericzinda/test/logic.pl").
ERROR: /Users/ericzinda/test/logic.pl:1:16: Syntax error: Operator expected
ERROR: /Users/ericzinda/test/logic.pl:2:17: Syntax error: illegal_character
ERROR: /Users/ericzinda/test/logic.pl:3:17: Syntax error: illegal_character
ERROR: /Users/ericzinda/test/logic.pl:4:17: Syntax error: illegal_character
ERROR: /Users/ericzinda/test/logic.pl:5:17: Syntax error: illegal_character
ERROR: /Users/ericzinda/test/logic.pl:9:27: Syntax error: Operator expected
ERROR: /Users/ericzinda/test/logic.pl:10:27: Syntax error: Operator expected
ERROR: /Users/ericzinda/test/logic.pl:11:27: Syntax error: Operator expected
ERROR: /Users/ericzinda/test/logic.pl:12:27: Syntax error: Operator expected
ERROR: /Users/ericzinda/test/logic.pl:20:16: Syntax error: Operator expected
true.

Once I set the encoding it appears to have at least ran (I’m not sure if false is the right result for the last statement because I haven’t tried to decode what logic.pl is doing…):

[debug] ?- set_prolog_flag(encoding,utf8).
true.

[debug] ?- consult("/Users/ericzinda/test/logic.pl").
true.

[debug] ?- result = intersection([A,(A→B)], [p, (p→q)], Aim).
false.

The simplest way to convert that to swiplserver is to literally take the commands and turn them into strings:

# test.py
from swiplserver import *

with PrologMQI() as mqi:
	with mqi.create_thread() as prolog_thread:
		result = prolog_thread.query("set_prolog_flag(encoding,utf8).")
		print(result)
		result = prolog_thread.query("consult(\"/Users/ericzinda/test/logic.pl\").")
		print(result)
		result = prolog_thread.query("result = intersection([A,(A→B)], [p, (p→q)], Aim).")
		print(result)

Running on the Macintosh command line gives the same result as the Prolog command line:

% python3 test.py
True
True
False

%
1 Like

This is a bit of a MacOS issue. SWI-Prolog gets its locale initialization from the environment (LANG and/or LC_* vars) as it is supposed to work on POSIX systems. AFAIK, these variables are by default not set on MacOS. You fix that for the shell by setting them in your shell profile file. That unfortunately doesn’t help for swipl-win, the app. If anyone knows how to initialise the POSIX locale handling in a MacOS app, please let me know.

If you have UTF-8 source files one should have them start with this directive (which may appear above the :- module(....).) to make the file load correctly regardless of the current locale. Ensuring the file has a BOM (Byte Order Mark) also works. Some editors can do that.

 :- encoding(utf8).
1 Like

I should have also pointed out that, once you’ve got things going, it is worth thinking about the interface between Prolog and your Python code. You should try to avoid a “chatty” interface (one where there is a bunch of back and forth low-level calls). Try to encapsulate what you’re doing in higher level predicates that do bigger chunks of work and call those. It will be easier to write and debug the code, and it will likely be a bit faster too since you won’t be incurring the cost of sending the information back and forth.