5 Calling Prolog from Python
All Application Manual Name SummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • SWI-Prolog Python interface
        • Calling Prolog from Python
          • Janus iterator query
          • Janus iterator apply
          • Janus access to Python locals and globals
          • Janus and Prolog truth
            • Janus classed Undefined and TruthVal
          • Janus class Term
          • Janus class PrologError

5.4 Janus and Prolog truth

In traditional Prolog, queries succeed or fail. Systems that implement tabling with Well Founded Semantics such as XSB and SWI-Prolog define a third truth value typically called undefined. Undefined results may have two reasons; (1) the program is logically inconsistent or (2) restraints have been applied in the derivation.

Because classical Prolog truth is dominant, we represent the success of a query using the Python booleans True and False. For undefined answers we define a class janus.Undefined() that may represent different levels of detail on why the result is undefined. The notion of generic undefined is represented by a unique instance of this class. The three truth values are accessible as properties of the janus module.

janus.true
This property has the Python boolean True
janus.false
This property has the Python boolean False
janus.undefined
This property holds a unique instance of class janus.Undefined()

5.4.1 Janus classed Undefined and TruthVal

The class janus.Undefined() represents an undefined result under the Well Founded Semantics.

Undefined janus.Undefined(term=None)
Instances are never created explicitly by the user. They are created by the calls to Prolog initiated from janus.query_once() and janus.query().

The class has a single property class term that represents either the delay list or the residual program. See janus.TruthVal() for details.

Enum janus.TruthVal()
This class is a Python enumeration. Its values are passed as the optional truth parameter to janus.query_once() and janus.query(). The defined instances are
NO_TRUTHVALS
Undefined results are reported as True. This is quite pointless in the current design and this may go.
PLAIN_TRUTHVALS
Return undefined results as janus.undefined, a unique instance of the class janus.Undefined().
DELAY_LISTS
Return undefined results as an instance of class janus.Undefined(). thats holds the delay list in Prolog native representation. See call_delays/2.
RESIDUAL_PROGRAM
Return undefined results as an instance of class janus.Undefined(). thats holds the residual program in Prolog native representation. See call_residual_program/2.

The instances of this enumeration are available as attributed of the janus module.

For example, given Russel's paradox defined in Prolog as below.

:- module(russel, [shaves/2]).

:- table shaves/2.

shaves(barber,P) :- person(P),  tnot(shaves(P,P)).
person(barber).
person(mayor).

From Python, we may ask who shaves the barber in four ways as illustrated below. Note that the Prolog representations for janus.DELAY_LISTS and janus.RESIDUAL_PROGRAM use the write_canonical/1 notation. They may later be changed to use a more human friendly notation.

# Using NO_TRUTHVALS
>>> janus.query_once("russel:shaves(barber, X)", truth_vals=janus.NO_TRUTHVALS)
{'truth': True, 'X': 'barber'}

# Using default PLAIN_TRUTHVALS (default)
>>> janus.query_once("russel:shaves(barber, X)")
{'truth': Undefined, 'X': 'barber'}

# Using default DELAY_LISTS
>>> janus.query_once("russel:shaves(barber, X)", truth_vals=janus.DELAY_LISTS)
{'truth': :(russel,shaves(barber,barber)), 'X': 'barber'}

# Using default RESIDUAL_PROGRAM
>>> janus.query_once("russel:shaves(barber, X)", truth_vals=janus.RESIDUAL_PROGRAM)
{'truth': [:-(:(russel,shaves(barber,barber)),tnot(:(russel,shaves(barber,barber))))], 'X': 'barber'}