The pyDatalog module has the following methods :
predicate_name(terms[0], terms[1], ...)
predicate_name(terms[0], terms[1], ...)
&
operator. It returns an instance of Answer, or None. The Answer class returned by ask(query
) contains the following attributes and methods:
In theory, the code string of a pyDatalog program can contain any python code, as defined in the official grammar of Python. However, function and variable names (that are not reserved by python) are considered Datalog symbols, have special meaning, and should appear only in statements that follow a subset of the python grammar, as defined below.
The terminal symbols in this grammar are defined in BNF as follows :
_pyD_
are reserved for pyDatalogPlease note:
=
" defines a logic formula, while "==
" appears in a fact, clause or query and must always be surrounded by parenthesisX==expr
must be bound by a previous literal (otherwise, no result is returned)p[X]< expr
must be bound (otherwise, no result is returned).X<expr
comparisons must be bound (otherwise, an error is raised)Aggregate functions:
(P[X]==len(Y)) <= body
: P[X] is the count of values of Y (associated to X by the body of the clause)(P[X]==sum(Y, for_each=Z)) <= body
: P[X] is the sum of Y for each Z. (Z is used to distinguish possibly identical Y values)(P[X]==concat(Y, order_by=Z, sep=',')) <= body
: same as 'sum' but for string. The strings are sorted by Z, and separated by ','.(P[X]==min(Y, order_by=Z)) <= body
: P[X] is the minimum (or maximum) of Y sorted by Z.(P[X]==rank(for_each=Y, order_by=Z)) <= body
: P[X] is the sequence number of X in the list of Y values when the list is sorted by Z.(P[X]==running_sum(N, for_each=Y, order_by=Z)) <= body
: P[X] is the sum of the values of N, for each Y that are before or equal to X when Y's are sorted by Z.order_by
arguments can be preceded by '-' for descending sort order. If the aggregation function does not depend on a variable, use a constant (e.g. P[None] == len(Y)
).Beware that, when loading a datalog program, a symbol could become a constant. For example,
@pyDatalog.program()
def _():
+ a(i)
for i in range(3):
+ b(i)
print(pyDatalog.ask("a('i')")) # prints a set with 1 element : the ('i',) tuple
print(pyDatalog.ask("b(X)")) # prints a set with 3 elements, each containing one element : 0, 1 or 2
The for
loop assigns an integer to i, which is inserted as a constant in + b(i)
.
Classes inheriting from pyDatalog.Mixin can participate in in-line queries. An in-line query follows the syntax of a body (see above), where:
X=pyDatalog.Variable()
or X,Y,Z=pyDatalog.variables(3)
pyDatalog.Variable
or python literals. (for example, A.p(X,A.b)
is not allowed)in
keyword must be replaced by a call to ._in( )
, e.g. a.p[X]._in((1,2)). not in
must be replaced by ._not_in( )
The result of an in-line query behaves like a python list, with a column for each variable, in order of their appearance in the query. Additionally, it has a >= X
operator which return the first value of variable X in the result of the query.
After an in-line query, each variable in the query behaves like a list of the result. Additionally, the first result (or None
) can be obtained with .v()
(e.g. X.v()
)