<p align="center">
  <img src="clyngor.png"/><br>
</p>

Handy python wrapper around [Potassco's Clingo](https://potassco.org/) [ASP solver](https://en.wikipedia.org/wiki/Answer%20set%20programming).



## Example
Clyngor offers multiple interfaces. The followings are all equivalent.
(they search for [formal concepts](https://en.wikipedia.org/wiki/Formal_concept_analysis))

    from clyngor import ASP, solve

    answers = ASP("""
    rel(a,(c;d)). rel(b,(d;e)).
    obj(X):- rel(X,_) ; rel(X,Y): att(Y).
    att(Y):- rel(_,Y) ; rel(X,Y): obj(X).
    :- not obj(X):obj(X).
    :- not att(Y):att(Y).
    """)
    for answer in answers:
        print(answer)

The same, but with the lower level function expecting files:

    answers = solve(inline="""
    rel(a,(c;d)). rel(b,(d;e)).
    obj(X):- rel(X,_) ; rel(X,Y): att(Y).
    att(Y):- rel(_,Y) ; rel(X,Y): obj(X).
    :- not obj(X):obj(X).
    :- not att(Y):att(Y).
    """)

More traditional interface, using file containing the ASP source code:

    answers = solve('concepts.lp'):  # also accepts list of file

More examples are available in [the unit tests](clyngor/test/).



## Chaining
Once you get your answers, clyngor allows you to specify
the answer sets format using builtin methods:

    for answer in answers.by_predicate.first_arg_only:
        print('{' + ','.join(answer['obj']) + '} × {' + ','.join(answer['att']) + '}')

And if you need a [*pyasp-like*](https://github.com/sthiele/pyasp) interface:

    for answer in answers.as_pyasp:
        print('{' + ','.join(a.args()[0] for a in answer if a.predicate == 'obj')
              + '} × {' + ','.join(a.args()[0] for a in answer if a.predicate == 'att') + '}')


Currently, there is only one way to see all chaining operator available:
[the source code of the Answers object](clyngor/answers.py).




## Alternatives
[pyasp](https://github.com/sthiele/pyasp) comes into mind, but do not (yet) supports clingo alone.



## Installation

    pip install clyngor

You must have `clingo` in your path. Depending on your OS, it might be done with a system installation,
or through downloading and (compilation and) manual installation.

[See the doc](https://potassco.org/doc/start/).




## Tips
### Careful parsing
By default, clyngor uses a very simple parser (yeah, `str.split`) in order to achieve time efficiency in most time.
However, when asked to compute a particular output format (like `parse_args`) or an explicitely *careful parsing*,
clyngor will use a much more robust parser (made with an [arpeggio](http://www.igordejanovic.net/Arpeggio/) grammar).

### Define the path to clingo binary

    import clyngor
    clyngor.CLINGO_BIN_PATH = 'path/to/clingo'

Note that it will be the very first parameter to [`subprocess.Popen`](https://docs.python.org/3/library/subprocess.html#popen-constructor).

### Dinopython support
No.

### Contributions
Yes.

### Why clyngor ?
No, it's pronounced [*clyngor*](https://www.youtube.com/watch?v=RyU99BCNRuU#t=50s).
