Change in scasp breaks MQI?

Using the latest stable swipl, and the most recent sCASP module from GitHub.

Queries that were going through MQI and using abducibility have stopped working. I noticed the problem yesterday, which makes me think that it is caused by the July 11 update to sCASP.

I have a file that if I load it in the toplevel and run the query, I get this as the answer:

?- blawxrun(person(X),Human,Model).
Human = query-[goal_origin(abduced(person(X)), <clause>(0x55becb3d9710))-[]],
Model = [not o_person(X), person(X)],
put_attr(X, scasp_output, name('A')) ;
false.

When I run the same query through MQI in Python, it stalls, which was the problem I was having some time ago about how MQI was dealing with attributed variables.

blawxrun just calls scasp/2 and ovar_analyze_term/2.

I note that the <clause> information is included in the explanation, which is new. I suspect means that something has changed in the defaults of one of those two predicates to use the source(true) feature in the new version of sCASP. And perhaps something has also changed in how scasp it returns the attributed variables data that has caused a regression of the problem we had with MQI previously?

I will try to come up with a small example .pl and .py that recreate the problem, and update here when I can manage it. Put I suspect anything using abducibility will trigger it.

Suggestions on whether this is the likely cause, and on a good workaround would be appreciated. I’m looking at just pulling an older version of the sCASP library until MQI can catch up.

Update: Reverting to 4a75bdaddbe17ad46b68f9a715d138fbddb83b78 hash for sCASP solves my problem, for now.

Hey,
Thanks for reporting!

I tried to reproduce this problem and I think it is indeed an issue with the way MQI handles clause references (see below).

It is true that clause references are now part of the Prolog representation of the justification tree, as obtained from the tree(-Tree) option of scasp/2. This is regardless of the new option source(+Bool) for justification_tree//2 which determines whether or not these clause references will be used for adding source references (file+line) in the HTML and natural language representations of the justification tree.

With the latest SWI-Prolog and s(CASP) I get the following:

% ~/foo.pl
:- use_module(library(scasp)).

#abducible person(_).

In the top-level:

?- consult('~/foo.pl').
true.

?- scasp(person(X), [model(M), tree(T)]).
M = [not o_person(X), person(X)],
T = query-[goal_origin(abduced(person(X)), <clause>(0x600001915b00))-[]] ;
false.

?- scasp(person(X), [model(M), tree(T)]), human_justification_tree(T, []).
   by abduction we conclude that person holds for anything
   ∎
M = [not o_person(X), person(X)],
T = query-[goal_origin(abduced(person(X)), <clause>(0x600003d6c900))-[]] .

?- scasp(person(X), [model(M), tree(T)]), human_justification_tree(T, [source(true)]).
   by abduction we conclude that person holds for anything [per ~/foo.pl:3]
   ∎
M = [not o_person(X), person(X)],
T = query-[goal_origin(abduced(person(X)), <clause>(0x600003d6c900))-[]] .

In a Python REPL:

In [23]: with PrologMQI() as mqi:
    ...:     with mqi.create_thread() as prolog_thread:
    ...:         result = prolog_thread.query("consult('~/foo.pl'), scasp(person(X), [model(M), tree(_)]).")
    ...:         print(result)
    ...:
[{'X': 'A', 'M': [{'args': [{'args': ['A'], 'functor': 'o_person'}], 'functor': 'not'}, {'args': ['A'], 'functor': 'person'}]}]

In [24]: with PrologMQI() as mqi:
    ...:     with mqi.create_thread() as prolog_thread:
    ...:         result = prolog_thread.query("consult('~/foo.pl'), scasp(person(X), [model(M), tree(T)]).")
    ...:         print(result)
    ...:
---------------------------------------------------------------------------
PrologError                               Traceback (most recent call last)
...
PrologError: type_error

In [25]: with PrologMQI() as mqi:
    ...:     with mqi.create_thread() as prolog_thread:
    ...:         result = prolog_thread.query("clause(lists:member(_, _), _, C).")
    ...:         print(result)
    ...:
---------------------------------------------------------------------------
PrologError                               Traceback (most recent call last)
...
PrologError: type_error

So AFAICT s(CASP) works basically as expected, but MQI throws a type error when trying to communicate clause references.

As for a workaround, the most straightforward seems to be stripping the source references from the justification term, one can simply replace every occurrence of goal_origin(T, _) with T.
We could add an option for doing that within scasp/2 to preserve the previous format, which is the same except for the added source references, WDYT?

I don’t see a lot of utility in the clause information for me personally, because my prolog code is being auto-generated, so the line numbers and file names are meaningless. I have a separate method of describing the provenance of the rules. So for my purposes, I’d prefer if the clause information was opt-in, or at least opt-out.

Opt-in would be more friendly, because it wouldn’t require anything on my end. But I’m aware that the API is unstable, at the moment.

For now, I’m using the version of the s(CASP) library prior to when the changes were made. If the clause information was optional, that would eliminate the need for a work-around, I think. Otherwise, it’s probably easier for me to just wait for MQI to be updated, and then deal with the changes.