Aluriak / clyngor

Handy python wrapper around Potassco's Clingo ASP solver.
GNU General Public License v3.0
34 stars 7 forks source link

How to get info on number of models generated? #22

Closed llaisdy closed 4 years ago

llaisdy commented 4 years ago

Dear Lucas

This is brilliant. Thank you very much for making it open-source!

Is there a way to get an indication of the number of models generated? If I run clingo on the commandline with a set number of models, clingo will tell me if there are more models available, e.g.:

$ clingo -n 500 program.lp
clingo version 5.4.0
Reading from program.lp
Solving...
...
SATISFIABLE

Models       : 500+
Calls        : 1
Time         : 0.002s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time     : 0.002s

The "+" in "Models: 500+" tells me there are more than 500 possibilities. Can I access that kind of info via Clyngor?

Thanks again

Ivan

Aluriak commented 4 years ago

Hi ! Sorry for the late reply.

Thank you :) Hope it serves you well.

I made a little example, that uses this line to access the 500+ value as a string:

n = models.statistics['Models']

You may want something like that for later use:

number, are_more = int(n.rstrip('+')), n.endswith('+')
llaisdy commented 4 years ago

That is perfect. Thanks very much!

llaisdy commented 4 years ago

Odd thing I've noticed (noting it here in case it's useful): The above example will only work if clingo's python package is not installed. If it is installed I get:

>>> import clyngor
>>> models = clyngor.solve(inline='1{n(1..1000)}1.', nb_model=500, stats=True)
>>> nb_model_found = 0
>>> for nb_model_found, model in enumerate(models, start=1):
...     pass
... 
>>> models.statistics['Models']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Models'

Uninstall clingo's python package, start a new python session, and:

>>> import clyngor
>>> models = clyngor.solve(inline='1{n(1..1000)}1.', nb_model=500, stats=True)
>>> nb_model_found = 0
>>> for nb_model_found, model in enumerate(models, start=1):
...     pass
... 
>>> models.statistics['Models']
'500+'

Is that expected behaviour?

Aluriak commented 4 years ago

Thanks for taking time to document that.

No, it's not expected officially, but it's expected behavior since there is little work on the statistics data structure when the clingo module is installed. This is due to the fact that using the clingo module, clyngor uses the API, whereas without the clingo module it parses the output, building the model.statistics dictionnary using clingo's stdout. In order to clyngor to reach production-grade concerning that aspect of clingo, we need to choose a data structure to encapsulate the statistics data (either a dict, or something looking like the object of clingo's API, or something else), and convert the obtained statistics to that data structure.

For the moment, i don't have time for such development. If that interests you, we can continue discussions at #23

llaisdy commented 4 years ago

Thanks for the explanation :) I'm happy just not using the clingo module (I think, ..., for now at least). Clyngor seems to provide what I'm looking for in terms of access to clingo from python. If it turns out I need both model.statistics and clingo's python package (I'm not entirely sure what the clingo python API provides) I'll be back and more than happy to work on development.

Aluriak commented 4 years ago

Cool ! Do not hesitate to open issues if you have more questions, remarks or inquiries.

Happy coding !