Pyke And Programming Languages

Here is the new header that I designed for ViralOne. I plan on updating that blog. The design isn’t completed, but it’s also getting me back into design.

Years ago, I studied computer programming. I was a decent programmer and worked for a few years in that domain. It must have been around 5 years.

Currently, my interest in programming has started once again. Honestly, when I started studying programming 1995, I really didn’t what I was getting myself into. It was only later that I really took a keen interest. I used to program in Visual Basic and C++. At the same time, I decided to pursue my interest in mathematics fulltime.

Right now, Python (with Pyke), AJAX, Ruby on Rails have my interest. Since I will be pursuing more scholarly subjects in the coming year, I plan on studying them and learning them as well. Since I have studied computer programming, I think that this will be a good challenge.

I was intrigued to learn of Pyke. The artificial intelligence angle got my interest. From the documentation on the website, Pyke is an inference engine completely written in Python. Simplistically, an inference engine is what an expert system uses to make decisions.

Let’s remind ourselves what exactly an inference engine is:

In computer science, and specifically the branches of knowledge engineering and artificial intelligence, an inference engine is a computer program that tries to derive answers from a knowledge base. It is the “brain” that expert systems use to reason about the information in the knowledge base for the ultimate purpose of formulating new conclusions. Inference engines are considered to be a special case of reasoning engines, which can use more general methods of reasoning.

Pyke is a knowledge-based inference engine (expert system) written in 100% python that can:

  • Do both forward-chaining (data driven) and backward-chaining (goal directed) inferencing.
    • Pyke may be embedded into any python program.
  • Automatically generate python programs by assembling individual python functions into complete call graphs.
    • This is done through a unique design where the individual python functions are attached to backward-chaining rules.
    • Unlike other approaches to code reuse (e.g. Zope adapters and generic functions), this allows the inference engine to ensure that all of the function’s requirements are completely satisfied, by examining the entire call graph down to the leaves, before any of the functions are executed.
    • This is an optional feature. You don’t need to use it if you just want the inferencing capability by itself.


The knowledge engine supports:

  • Multiple fact bases, each with its own list of facts.
  • Both forward-chaining rules and backward-chaining rules.
  • Multiple rule bases, each with its own list of forward-chaining and/or backward-chaining rules.
  • Rule base inheritance — activating the derived rule base includes the rules from the parent rule base.
  • The inference rules are compiled into python functions, allowing python code snippets to be used within the rules. This greatly enhances the expressiveness of the rules.


Automatic program generation:

  • Calls the generated python programs plans.
  • Plans may be run multiple times without needing to rerun the inference rules.
  • Plans may be pickled and cached to disk to be used by other programs or in later runs of the same program.
  • No pyke modules are required to run the plans.


Potential pyke applications:

  • Complicated decision making applications.
  • The back-end (code generation and optimization) of compilers. Pyke is used as the back-end of its own compiler that translates rules into python code.
  • Automatic SQL statement generation.
  • Automatic HTML generation and automatic HTML template processing.
  • Automatic program builder to reuse a common set of functions for many different specific situations. This could also easily incorporate a new custom function into a much larger program, where the use of the custom function might influence the choice of other standard functions in other parts of the program.
  • The control module for a web framework tool.
  • A high-level planner to automatically distribute the modules of a large system over several computers in a distributed system to meet specific performance and capacity goals. This could be used to automatically scale the same system code from a small one program, one computer system to much larger distributed systems to meet a wide range of performance goals.
  • Diagnosis systems, including automated customer service systems.
  • Program or library customization for specific uses.
  • In addition to being able to build programs, pyke can instantiate, configure and interconnect a network of objects to meet a specific need or situation.





Pyke is an inference engine that applies rules to facts to establish additional facts (through forward-chaining rules), and/or to prove goals and optionally assemble python functions into customized call graphs, called plans (through backward-chaining rules).

Pyke may then be reset, deleting the last set of facts, so that the cycle may be repeated. For each cycle a different rule base may be activated.

The plan capability allows the postponement of code execution until the top-level goal has been completely proven. This shields the code from blind alleys and backtracking within the rules.

Once a plan has been created, it may be executed multiple times with different arguments. It may also be pickled, and later run again without requiring any pyke modules.




Knowledge Bases

Knowledge is made up of both facts and rules. These are organized into named repositories called knowledge bases. A knowledge base is like a directory for files on disk, except that knowledge bases may not be nested. Therefore, facts and goals always have a two-level name.

Here are some examples of facts you might see in a web server application:







request.path_segment(0, my)

request.path_segment(1, 'site.html')

request.path_segment(-2, my)

request.path_segment(-1, 'site.html')

Note that three different knowledge bases (all fact bases) are shown here named header, cookie, and request; each with multiple facts.

There are different types of knowledge bases.

  • Those that contain facts are called fact bases.
  • Those that contain rules are called rule bases.
  • It is also possible to create other kinds of knowledge bases that lookup facts and prove goals in different ways. The only one of these in pyke is the special knowledge base.

All knowledge bases share the same name space; so that no two of them, regardless of their type, may have the same name.




Premises and Conclusions

Rules have two parts to them: an if part (the premises), and a then part (the conclusions). (Though pyke uses different names for these). Each of these if and then parts contain one or more facts or goals represented by patterns.

Logically, the rule says that if all of the premises in the if part of the rule are true, then each of the conclusions in the then part of the rule must also be true.



Rules are specified individually within a rule base. They are not nested or explicitly linked to each other. So pyke must automatically figure out how to combine these rules to accomplish some larger task. This is called inferencing and there are two different approaches that pyke uses, depending on the rule’s type.


Plans and Automatic Program Generation

Once you understand how backward-chaining works, it is relatively easy to do automatic program generation.


Adding Plans to Backward-Chaining Rules

The way this is done is by attaching python functions to the backward-chaining rules. These functions are written at the end of each rule in the .krb file. They don’t affect how the rules run, but are gathered up to form a call graph that is returned along with the pattern variable bindings that prove the top-level goal.



Consider a small rule base to construct programs to transfer money between bank accounts. Each from_acct and to_acct takes one of two forms:

  1. (name, account_type)
    • This is a local account with this bank.
    • Example: (‘bruce’, ‘checking’).
  2. (bank, name, account_type)
    • This is a foreign account with another bank.
    • Example: (‘my_other_bank’, ‘bruce’, ‘checking’).

At least one of the bank accounts must be a local account.

Here’s the example rule base:

 1  transfer1:

 2      use transfer($from_acct, $to_acct) taking (amount)

 3      when

 4          withdraw($from_acct)

 5              $$(amount)

 6          deposit($to_acct)

 7              $$(amount) 8  transfer2:

 9      use transfer($from_acct, $to_acct) taking (amount)

10      when

11          transfer_ach($from_acct, $to_acct)

12              $$(amount)

13  withdraw:

14      use withdraw(($who, $acct_type)) taking (amount)

15      with

16          print "withdraw", amount, "from", $who, $acct_type

17  deposit:

18      use deposit(($who, $acct_type)) taking (amount)

19      with

20          print "deposit", amount, "to", $who, $acct_type

21  transfer_ach1:

22      use transfer_ach($from_acct, ($bank, $who, $acct_type)) taking (amount)

23      when

24          withdraw($from_acct)

25              $$(amount)

26          deposit((central_accts, ach_send_acct))

27              $$(amount)

28      with

29          print "send", amount, "to bank", $bank, "acct", $who, $acct_type

30  transfer_ach2:

31      use transfer_ach($from_acct, $to_acct) taking (amount)

32      when

33          get_ach($from_acct)

34              $$(amount)

35          withdraw((central_accts, ach_recv_acct))

36              $$(amount)

37          deposit($to_acct)

38              $$(amount)

39  get_ach:

40      use get_ach(($bank, $who, $acct_type)) taking (amount)

41      with

42          print "get", amount, "from bank", $bank, "acct", $who, $acct_type


Running the Example

The plan is created as a byproduct of proving the goal:

>>> import pyke

>>> pyke.load('examples')

>>> pyke.activate('plan_example')

>>> no_vars, plan1 = pyke.prove_1('plan_example', 'transfer',

...                               (('bruce', 'checking'),

...                                ('bruce', 'savings')),

...                               0)

plan1 is now a program to transfer X amount from ‘bruce’, ‘checking’ to ‘bruce’, ‘savings’.

>>> plan1(100)

withdraw 100 from bruce checking

deposit 100 to bruce savings

The program may be used multiple times:

>>> plan1(50)

withdraw 50 from bruce checking

deposit 50 to bruce savings

Notice the strings: bruce, checking and savings in the output. These were specified as pattern variables in the code and are cooked into the plan along with the function call graph.

Let’s create another program:

>>> no_vars, plan2 = pyke.prove_1('plan_example', 'transfer',

...                               (('my_other_bank', 'bruce', 'checking'),

...                                ('bruce', 'savings')),

...                               0)

plan2 is now a program to transfer X amount from ‘my_other_bank’, ‘bruce’, ‘checking’ to ‘bruce’, ‘savings’.

>>> plan2(150)

get 150 from bank my_other_bank acct bruce checking

withdraw 150 from central_accts ach_recv_acct

deposit 150 to bruce savings

And the final use case:

>>> no_vars, plan3 = pyke.prove_1('plan_example', 'transfer',

...                               (('bruce', 'checking'),

...                                ('my_other_bank', 'bruce', 'savings')),

...                               0)

>>> plan3(200)

withdraw 200 from bruce checking

deposit 200 to central_accts ach_send_acct

send 200 to bank my_other_bank acct bruce savings



So you can see that it quite easy to use pyke to automatically combine python functions into programs!

It also allows data within each python function to be specified using a pattern variable so that pyke can customize these values to match the specific situation.

Most text taken from the Pyke homepage.

Author: range

I'm mathematician/IT strategist/blogger from Canada living in Taipei.