Roadmap and change log


The goal is to make pyDatalog the easiest way to develop the business logic of applications, thanks to logic programming.  If you are interested to contribute to pyDatalog, please contact me.

To do :
  • improve performance by memoizing intermediate results within a transaction
  • support anonymous variable '_'
  • import pyDatalog files, as in Hy
  • use pyrsistent to represent literals and clauses ?
  • rewrite Engine using mochi ?
  • methods to load facts when needed for a predicate, from csv or SQL data sources
  • support for dictionary in expressions
  • support pyMongo-like queries on relational databases, using a dictionary of criteria e.g. Employee.find({"salary": {"$lt": 5000}})
  • align to open-source best practices
  • support for equation solver : (X==Y+Z) <= (Y==X-Z)
  • boolean function can be used as predicate in a body
  • support active clauses to automatically insert facts, as in statelog :  +head <= body
  • transactions with incremental error detection :  +(Employee.salary[X]==Y) => (0 <= Employee.salary[X]) | "Salary of {X} must be positive, not {Y}"
  • convert Datalog to SQL when possible, for better performance
  • calculated class attributes (with forward chaining)
  • support Google Apps Engine's datastore
  • use SLG resolution algorithm

Change log

In bold : changes that may impact existing pyDatalog programs

Latest bitbucket version : 

see commits :

0.17.1 - 24 Jan 2016

  • fix 'in' operator in 3.5 by releasing from master branch.

0.17 - 20 Jan 2016

  • promote previous release candidate

0.17.0rc1 - 14 Dec 2015

  • improve documentation,  examples
  • wheels for Python 3.5 on Windows
  • accept  logging.isEnabledFor to control logging

0.16.0 - 5 July 2015

  • upstage the release candidate version

0.16.0rc1 - 26 May 2015

  • significant rewrite of the resolution engine:
    • improve speed of recursive literal. Hashtag_optimized solved under 6 seconds
    • improve speed of aggregate functions and clauses with negation, by reusing memoized intermediate results
    • enforce order of iterative functions
  • fix issue #7 : hashtag_optimized finds a path, but not the shortest one
  • fix issue #14 : incorrect result in special case of a literal with 2 identical variables

0.15.2 - 1 Mar 2015

  • fix issue #13 : PyPi package wrong case in

0.15.0 - 14 December 2014

  • reset a predicate, for use in interactive consoles : p(X) <= None 

0.15.0c1 - 5 October 2014

  • add .sort() for in-line queries
  • improve performance by compiling the resolution engine with Cython
  • issue #12 : don't show version number on import pyDatalog
  • issue #11 : error in (Y == 1/X)
  • issue #10 : TypeError when using a prefixed resolver
  • issue #9 :  terms created by create_terms are now recognized by pyDatalog.load
  • issue #8 : support for nested queries (a resolver in python can ask another query)
  • add mean_ and linear regression_ aggregate function

0.14.6 - 19 August 2014

  • Several fixes, including:
    • issue #4 : max_ aggregate function had side effects on other clauses
    • issue #6 : exceptions were raised in expressions that should not be evaluated
    • changeset 59cd787: avoid confusion between similar heads of a functional clause
  • add support for slices in pyDatalog programs and dynamic queries
  • various code, performance and documentation improvements

0.14.5 - 23 March 2014

  • added support for unicode
  • rank, running_sum now use group_by instead of for_each. Improved speed of aggregation
  • literals can now have keyword arguments (e.g. parent(of=X, is_=Y) )

0.14.1 - 23 February 2014

  • hot fixes :
    • fix the plan of resolution of functional clauses, so that the first, most general rule is always evaluated last
    • fix initialization bug in Logic()
    • support for python classes (e.g. str() ) in logic clauses.  Allow logic functions f[X] in the argument of python calls within logic clauses
  • Examples:
    • add to illustrate graph algorithms
    • simplify
    • illustrate how to interact with users in the tutorial

0.14.0 - 27 December 2013

  • support for calls to standard library in expressions (with bound variables) 
  • make queries thread-safe
  • support for expert systems, through ordered evaluation of the clauses defining a function (resolution stops after the first match)
  • support for multiple logic models, through Logic()
  • create_atoms() is replaced by create_terms()
  • support for the power operator (e.g. X**2)
  • del f[constant] removes any fact for f[constant]
  • del f[X] removes any clauses for f[X]
  • remove "six" dependency at installation
  • small fixes and speed improvements:
    • True and 1 should be 2 different constants
    • the value extracted by >= X should be the same as X.v()for queries returning True
    • add format_ atom 

0.13.0 - 17 April 2013 (Documentation)

  • support for SQLAlchemy 8.0
  • support for (nested) list data structure:
    •  unification of a variable to a nested list
    •  unification of 2 nested lists
    •  support for indexing and slicing of a list
    •  len_, range_, tuple_ function
    •  add generic N-queen example
  • support for "existential" literals
    •  asserting pos(X, Y) <= (X>0),  then Pos(1,Y) will return True
    •  negated literal in a clause do not bind unbound variables anymore
    •  add example
  • consistent handling of results of both in-line queries and pyDatalog.ask():
    •  return [] if no result found for in-line query (ask() returns None in this case)
    •  return [()] if there is no variable in a query that has a result
    •  return True if a variable is left unbound in a query that has a result
    •  return one column for each variable, in their order of appearance in the query
    •  pretty print the result of in-line queries
  • redesign of the expression engine:
    •  full support of function of a function, or function of an operation
    •  support unary operators (+, -)
    •  evaluate a sub-expression as soon as its variables are bound
  • performance improvement
    •  stop searching when a (sub-)goal is reached
    •  improve speed of long running queries
  •  other improvements:
    •  support for float, decimal
    •  add format_(string, value1, value2,..) for string formatting
    •  use logging module in Debug and Trace mode
    •  add arity to name of Python resolver
    •  align function names to PEP8 standard
    •  simplify code, improve documentation of source code (see 

0.12.0 - 3 Januay 2013 (documentation)

  • add pyDatalog.create_atoms() to support unprefixed inline queries and clauses
    • use the _ prefix for _len, _sum, _min, _max to avoid name conflict with Python
    • use ._in and ._not_in (instead of in and not in) to avoid name conflict with Python
    • update examples to use create_atoms()
  • various refactoring and bug fixes

0.11.2 - 2 Novembre 2012 (documentation)

  • add example for mongoDB support
  • fix issue with unreferenced pyDatalog.Mixin instances, by running garbage collector before accessing them
  • fix "subscript out of range" error with some in-line conjunctive queries
  • fix typo in, which also broke example

31 October 2012

rename version 8.1  and 9.0 to 0.8.1 and 0.9.0 on pypi.  Build using these specific versions will need to be updated.

0.11.1 - 26 Septembre 2012

Include "Examples" directory in distribution

0.11 - 25 September 2012

Prefixed clauses can now be inherited from parent classes.
Intermediate variables are not included in answers anymore.
Improve trace messages in Debug mode

Grammar enhancements:
  • support expressions in predicate, e.g. odd(N-1)
  • accept function, lambda as arguments of functions, e.g. f[f[X]]==Y
  • negated literal can now have unbound variables.  These variables are left in an undefined state, and should not be used further in the clause or query
  • support for negation of conjunctions : ~(p(X) & q(X))
  • support for clause retraction, using '-', e.g.  -(head <= body)
  • support for not in operator, e.g. X not in (1,2)
Python resolvers:
  • add arity to the name of python resolvers (e.g. _pyD_x1)
  • use WeakSet for the registry of pyDatalog.Mixin instances
  • support for generic resolvers, cls._PyD_query
  • now covers 98% of code in,,
  • improve queens solution
  • move the examples to a separate directory
  • fix rare KeyError when creating interned objects
  • fix possible stack overflow after resolving an aggregate clause

0.10.0 - 5 September 2012

None, 0 and "":
  • p[X]==None can now return values.  
  • fix : p[X]==0 and p[X]=="" now return values
Syntax enhancements:
  • support for p[X]<Y+Z, a.p[X]<Y+Z, and y==f[N-1].  Query results will have extra columns though.
  • support for X in Y+Z, p[X] in Y+Z, a.p[X] in Y+Z.  Query results will have extra columns though.
  • pyDatalog.variables(n) is a convenience function that creates n pyDatalog Variables (for use in in-line queries)
  • raise an error if the right hand side of a comparison is unbound
  • fix the issue with version number when importing pyDatalog
  • fix: names starting with a '_' are now considered as Variables in pyDatalog program
  • fix syntax error in '_example" with python 3.2

9.0 - 30 August 2012

Aggregate function:
    • support of rank(for_each=X, order_by=Y)
    • support of running_sum(N, for_each=X, order_by=Y)
    • replace key by more meaningful names : sum(X, for_each=Y), concat(X, order_by=Y, sep=Z), min(X, order_by=Y), max(X, order_by=Y)
In-line queries:
    • support for conjunctive queries : E.p(X) & E.q(X,Y) 
    • convenient access to the first variable value : X.v() and E.p(X) >= X
    • 20 ... 25 % speed improvement
    • support for predicate resolvers written in python
    • detect more syntax errors in clauses and queries
    • improved solution to the 8-queens problem

8.1 - 24 July 2012 (Documentation)

  • add hook for other database connectors
  • print Datalog error nicely
  • fix rare "string indices must be integers, not Symbol" error
  • accept "(X==Y)" where both are unbound
  • accept empty string as constant
  • pyDatalog.__version__ contains the version number

0.8.0 - 16 July 2012

  • allow function within expressions; support direct formula : a[X] == b[X]*2
  • support 'X in range(n)' literals
  • improve documentation
  • interactive datalog console
  • virtual attributes to python classes (e.g. Mary.salary_class)
  • allow customisation of Answer class
  • simplify code by eliminating lua engine

0.7.0 - 10 July 2012

  • support of function, i.e. predicate with unicity (e.g. father[x] == v is equivalent to father(x,v) with unicity per x)
  • support for aggregation predicate (len, sum, concat, min, max)
  • properly handle python queries with repeated variables (Employee.manager(X,X)
  • fix for pyDatalog.clear()

0.6.0 - 30 June 2012 (documentation)

  • use the just-in-time compiler of pypy instead of lupa's.  Stop development on lua engine 
  • support python objects in literals (python engine only)
  • support query of relational database via SQLAlchemy
  • support trace mode
  • Do not accept python variables (starting with _) in pyDatalog.program anymore
  • Equality predicate now accepts that both sides are bound
  • Accept upper case for predicate initials
  • new assert_fact() accepts python objects for terms

0.5.0 - 20 June 2012: (Documentation)

  • support for negation

0.4.0 - 3 May 2012: (Documentation)

  • support multi-line strings in pyDatalog.load()
  • go beyond 4 operators in expressions : use lambda

0.3.2 - 29 Apr 2012: 

  • index the database of facts for improved performance
  • make pyDatalog.clear() work

0.3.0 - 25 Apr 2012: (Documentation)

  • add the datalog engine written in python. Use it by default
  • use numeric type in results (instead of string types)
  • tested with python 2.7 and 3.2

0.2.1 : 16 Apr 2012 (Documentation)

  • rename "execute()" into "load()"
  • avoid stack overflow due to deep recursion
  • propose default datalog engine in the decorator, and add pyDatalog.ask(code), 

0.1.1 : 13 Apr 2012

  • add links to download in Pypi

0.1.0 : first release on Pypi (Documentation)