Search code examples
pythonfileprologloadswi-prolog

Python: swiplserver load prolog file


Based on this post try to follow the hint with setup some swiplserver

from pyswip import Prolog, Functor, Query
from swiplserver import PrologMQI, PrologThread


prolog = Prolog()
prolog.consult("Prolog/logic.pl")

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

My problem now, I did not know, how to load the "logic.pl":

:-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).

into that server setup, so I can use the statement:

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

Is there a way to use "logic.pl" similar to consult-command from pyswip?


Solution

  • [Copied from the same cross posted question on swi-prolog.discourse.group]

    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.

    Since logic.pl contains multibyte characters and I am on a Macintosh which doesn't set the encoding by default, I needed to either:

    • Put this at the top of logic.pl: :- encoding(utf8).
    • Put a byte order mark at the top of the file
    • Call set_prolog_flag(encoding,utf8). first (which is what I opted to do)

    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 start converting 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
    
    %
    

    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.