I am looking to design a system that will essentially need to make decisions based on input. The input will be a person.
class Person:
def __init__(self, name, age, sex, weight, height, nationality):
self.name = name
self.age = age
self.sex = sex
self.weight = weight
self.height = height
self.nationality = nationality
We want to assign each person to a school class based on certain rules.
For example:
Women from the UK between 22-25 should go to class B. Men over 75 should go to class A. Women over 6ft should go to class C.
We will have approximately 400 different rules and the first rule that is met should be applied - we need to maintain the order of the rules.
I am thinking about how to store/represent the rules here. Obviously, you could just have a veeeery long if, elif, elif
statement but this isn't efficient. Another option would be storing the rules in a database and maybe having an in memory table.
I would like to be able to edit the rules without doing a release - possibly having a front end to allow non tech people to add, remove and reorder rules.
Everything is on the table here - the only certain requirement is the actually programming language must be Python.
Added for further context
I suppose my question is how to store the rules. At the moment it is one huge long if elif elif
statement so anytime there is a change to the business logic the PM does up the new rules and I then convert them to the if statement.
All inputs to the system will be sent through the same list of rules and the first rule that matches will be applied. Multiple rules can apply to each input but it's always the first that is applied.
e.g.
Women over 25 go to Class B
Women go to Class A.
Any women over 25 will be sent to class B even though the second rule also applies.
Input will always contain the same format input - haven't decided where it will be an object or a dict but some of the values may be None
. Some Persons may not have a weight associated with them.
Rather than re-inventing the wheel, I'd suggest you to use some readily available solution. There are several expert systems out there and I'll focus on those which are either in Python or can be used via Python.
CLIPS
is an expert system originally developed by NASA. It's considered state of the art and used in university courses when teaching basics of AI. It's a great starting point due to its excellent documentation.
Its syntax is definitely not Python, it rather reminds of Lisp. The advantage of CLIPS
is that is a solid C engine which can be fully integrated with any other Python system via its bindings: the older pyclips and the newer clipspy. The bindings allow to embed Python code within the CLIPS language making it very easy to extend.
Rules can be loaded at runtime without the need of restarting the engine which should better suit your need.
The Python Knowledge Engine
it's a fairly powerful logic programming framework. As for CLIPS
, PyKE
comes with its own syntax to express rules and relies on Python for implementing the mechanics.
In other words, you write what to do in Python and you express when and how via rules.
Rules can be activated and deactivated on demand. This should allow you to support releaseless updates.
Durable Rules
is a fairly new project with the ambition of supporting multiple programming languages (Python, Node.js and Ruby so far).
Durable Rules
allow you to write the whole knowledge base (facts and rules) in Python. The syntax might look a bit weird though, a note in this regards at the end of the post.
I am not sure if you can update the rule-set while the system is online.
Apart from the multiple syntax support, what interest me of this project is the fact the core is a C based implementation of RETE
built on top of Redis DB. On a long run, this might lead to some interesting development.
These projects allow to express knowledge bases mostly in Python. I have never seen them in action and I am not sure about their performance and feature support.
The main reason I recommend against brewing your own rule engine to use in production is that, despite it seems an easy task at first, it quickly becomes evident that the problem domain is way bigger than predicted.
Python OOP nature seems initially a good fit for expressing knowledge as both Rules and Facts could be simple classes.
Nevertheless, as soon as the pattern matching becomes a little more complex (Employee
must have worked > 3 years in Company
which Stock
value is < 10$ in the last 3 years) two things become evident.
and
, or
, not
, is
, ... make things really hard to readMoreover, forcing the employees of an organization to use yet-another-in-house-built-language is usually a bad idea. It prevents them from learning something used in broader contexts such as CLIPS
or Drools
and will get you stuck in a maintenance/documentation loop for a long time.