SWI-Prolog / packages-mqi

Machine Query Interface
16 stars 5 forks source link

MQI Stalls when s(CASP) queries return clause information #18

Open Gauntlet173 opened 2 years ago

Gauntlet173 commented 2 years ago

I commented on this at the swi-prolog discourse group some time ago, and Oskardrums confirmed that the problem was with MQI in the post below.

https://swi-prolog.discourse.group/t/change-in-scasp-breaks-mqi/5609/2

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

I know the s(CASP) library is unstable, but I'm hoping the problem would be worth fixing, anyway. If MQI isn't able to deal with the most recent version of the s(CASP) library, I'll probably have to refactor my code to use pengines, or something, and I'm way to lazy for that. ;)

JanWielemaker commented 2 years ago

The clause references make little sense at the client side, so you must decide on what you want to do when them. One option is to map the goal_origin/2 as in

map_goal_origin(goal_origin(Goal, _), Goal).

     ....,
     mapsubterms(map_goal_origin, ScaspOutput, FinalOutput).

Another definition of map_goal_origin could go like this, getting file and line of the clause. Note that it might not be a clause or the clause may not have source information.

map_goal_origin(goal_origin(Goal, Clause), goal_origin(Goal, File:Line)) :-
     blob(Clause, clause),
     clause_property(Clause, file(File)),
     clause_property(Clause, line_count(Line)),
     !.
map_goal_origin(goal_origin(Goal, _), Goal).

Not tested. Except small typos I'm pretty sure this should work.

Gauntlet173 commented 2 years ago

For my purposes clause information might be very useful on the client side. In legal knowledge representation, file names could be used to link code to corresponding sections of law, which can be used to annotate justifications with the source legislative material.

Right now I'm doing that in another way, but if it was native to the reasoner that would probably simplify and speed up my code.

Do I take it correctly that for the time being there is no plan to make MQI handle it natively? That the only solution is to reformat it in Prolog into a format MQI can handle in the ways you suggest?

Thanks again.

JanWielemaker commented 2 years ago

Do I take it correctly that for the time being there is no plan to make MQI handle it natively? That the only solution is to reformat it in Prolog into a format MQI can handle in the ways you suggest?

Inside s(CASP), source references are clause references. That is the most efficient and precise representation. These are so called Prolog blobs and blobs are notoriously hard to communicate to the outside world. On purpose. So, if you want to send this information to the outside world the best option is to translate it into something else. We could change MQI to pass on the clause reference, but you cannot pass it back to Prolog, so all you have is <clause>(address), which is rather meaningless.

Gauntlet173 commented 2 years ago

I think we are missing the point.

You seem to be saying "here's how you can solve the problem in Prolog, and you probably don't want this information anyway."

I don't want to rewrite my prolog to workaround the MQI bug.

I want the MQI bug fixed.

When it receives a clause reference, it stalls. Blobs being difficult to communicate may be intentional, but MQI stalling can't be.

Maybe fixing it is not feasible, or not worth the effort. If so, great. Just let me know.

Rather than add more hacks I don't really understand to my prolog code, I will pin to an old version of s(CASP) until I can migrate away from MQI to something that works better. I'll just pay the technological debt rather than incurring more of it.

EricZinda commented 2 years ago

@Gauntlet173 If I follow all this, I think you're saying that simply having MQI not throw an error is enough of a workaround for you? Even if the blob that gets returned is not useful?

Gauntlet173 commented 2 years ago

That's exactly what I'm saying, @EricZinda. Drop the blob, and throw a warning.

If blobs are an expected part of SWI-Prolog's interface, MQI should handle them gracefully, and if they aren't s(CASP) shouldn't send them. Either way it doesn't seem like a thing that should need to be fixed in user code.

JanWielemaker commented 2 years ago

MQI not stalling on a blob is of course a good idea. It does not really solve the problem at hand though. Blobs are designed to safely represent internal resources, typically as a wrapped pointer. They cannot be passed to external processes to ensure this safety. More accurately, you can pass the printed representation to an external process, but you cannot read it back. As the serialized blob holds no meaningful information it makes little sense to send it to an external process.

There is no problem is s(CASP) as a Prolog library as that is still the same process, so Prolog can inspect the blobs. The scasp executable doesn't emit blobs. If you use something (MQI) to make the Prolog data accessible from an external process you need to take care of the blobs. One option is to make sure they do not appear (I think there is an option source(false) to sCASP). The other is to rewrite the data structure that holds the blobs, replacing the blob to the info you want from it. Typically that will be the file and line, but you could also have situations where you want the actual clause as a Prolog term.

In general, when using MQI, I think you should wrap the Prolog code you want to query into something that makes the output easy to digest by the external process. In fact, that also applies to communicating Prolog data in the same process to other languages. Prolog (attributed) variables and blobs are hard or impossible to interpret in most other languages.

But still, MQI not stalling is of course better :smile:

EricZinda commented 2 years ago

I'll figure out a fix to MQI throwing, but I won't be able to get to it until next week.

Gauntlet173 commented 1 year ago

I take your point, @JanWielemaker that s(CASP) as a library is fine returning blobs, because it sits inside the Prolog runtime world thingy, and that it doesn't solve the problem of getting access to what's inside the blob that's useful.

For me, rewriting the Prolog to massage the blob content is an adequate solution if you want the data, and that solution already exists. So the only remaining problem is the crashing, which happens even if you don't want the data.

I will also take a look and see if I can find the source(false) option for the scasp library, thanks.

No rush, @EricZinda, particularly if I can find the source(false) option somewhere.

Thanks, both.