yuce / pyswip

PySwip is a Python-Prolog interface that enables querying SWI-Prolog in your Python programs.
https://pyswip.org
MIT License
482 stars 98 forks source link

Multiple Prolog/swipl instances #107

Closed shoeffner closed 4 years ago

shoeffner commented 4 years ago

I am using Prolog's RDF reasoning abilities (especially rdf_db:rdf_reachable/5) inside a Python function.

Roughly it goes like this:

  1. Serialize an rdflib graph to a NamedTemporaryFile
  2. Run prolog.query(f"rdf_db:rdf_load('{tempfile.name}'), !, rdf_db:rdf_reachable(...)") to get the results.

However, as the Prolog class is implemented as a singleton, subsequent calls to that function (with potentially changed graph properties, or simply because I have it in a jupyter notebook) keep adding to the rdf_db triple store (as it is stored globally in swipl), growing it bigger and resulting in bloated result sets from the query (e.g., if it's 5 results on the first run, it might already be 20 or so on the second, 100s on the thirds, and after the 5th or so run already go into 1000s of results).

I figured that one way to get around this is to change my prolog query to include rdf_db:rdf_reset_db. But, from the examples in the Readme I didn't realize that Prolog was a singleton, as it goes all the way to creating an instance etc, where instead the classmethods could be used like this:

Prolog.consult(...)
Prolog.query(...)

instead of

prolog = Prolog()
prolog.consult(...)
prolog.query(...)

which conveys a very different picture to me as a reader/user.

Thus my question/request: Are there any plans to actually support multiple swipl instances or to clean them up properly? Something such as

with Prolog() as p:
    p.consult(...)
    p.query(...)

Or simply instances which clean up when they go out of scope would be very nice for my use case.

Either way, it is not super important for me – as mentioned above I found a way around it – but it might be interesting for other use cases which do not have the ability to clean up their swipl memory easily.

shoeffner commented 4 years ago

Okay, I guess I searched for the wrong terms. This is a duplicate of #74, so I will close it.

allComputableThings commented 4 years ago

I asked the SWI maintainers about the same question. I found two approaches to implement the many world model:

1) assert temporary facts in a new module, and retract all the fact (or predicates) in that module. (you can automate this using Python's with)

2) use a more OO style of Prolog. See https://github.com/LogtalkDotOrg/logtalk3/blob/21e41e71153c0500102ee77590c8b8480725494b/examples/design_patterns/ai/many_worlds/NOTES.md https://swi-prolog.discourse.group/t/threaded-queries-rulebase-independence/1236

shoeffner commented 4 years ago

Thanks a lot! I will stick to simply cleaning up the rdf database, as I don't need to reload other predicates or facts, only the triples. But I will keep this in mind in case I need to go that way!