Michael presents his work creating a rules engine based on Python. This should be an interesting subject – there are few rules solutions based on dynamic languages.
Michael reviewed his choices as he was trying to find a solution for a rules-based policy engine tightly integrated to the Python world:
- use an existing rules solution
- Pyke
- Pychinko
- Fuxi (based on Pychinko)
- these come from worlds that are wider than pure rules for policies, and carry a fair amount of complexity and weight
- integrate with a non-Python solutionDrools with Python through IPC, solutions that make the Python integration brittle and cumbersome
Which basically pushed Michael into creating his own solution. Creating your own rules solution tends to be something that the Python community – very much re-use oriented and very proud of the productivity that can be achieved with that language, and its expressive power and applicability – does not enthusiastically endorse. See for example this Stackoverflow discussion: http://stackoverflow.com/questions/467738/implementing-a-rules-engine-in-python. An even more confrontational point of view can be found here: http://catherinedevlin.blogspot.com/2009/06/dont-need-no-stinking-rules-engine.html
Michael shared his key choices
- ANTLR provides the key support to create and maintain languages
- The DSL approach easily supported by ANTLR(on DSLs, check Fowler’s book)
The details of his implementation can be found on Github at https://github.com/nemonik/Intellect
An example rules base (obtained from Github):
import logging first_sum = 0 second_sum = 0 rule "set both first_sum and second_sum to 1": agenda-group "test_d" then: attribute (first_sum, second_sum) = (1,1) log("first_sum is {0}".format(first_sum), "example", logging.DEBUG) log("second_sum is {0}".format(second_sum), "example", logging.DEBUG) rule "add 2": agenda-group "test_d" then: attribute first_sum += 2 attribute second_sum += 2 log("first_sum is {0}".format(first_sum), "example", logging.DEBUG) log("second_sum is {0}".format(second_sum), "example", logging.DEBUG) rule "add 3": agenda-group "test_d" then: attribute first_sum += 3 attribute second_sum += 3 log("first_sum is {0}".format(first_sum), "example", logging.DEBUG) log("second_sum is {0}".format(second_sum), "example", logging.DEBUG) rule "add 4": agenda-group "test_d" then: attribute first_sum += 4 attribute second_sum += 4 log("first_sum is {0}".format(first_sum), "example", logging.DEBUG) log("second_sum is {0}".format(second_sum), "example", logging.DEBUG) halt rule "should never get here": agenda-group "test_d" then: log("Then how did I get here?", "example", logging.DEBUG)
The complete implementation amounted to approximately 16000 lines of code.
Jacob Feldman shared his experience with a Python-based constraint engine that may be able to complement this solution.
Learn more about Decision management and Sparkling Logic’s SMARTS™ Data-Powered Decision Manager