Just for kicks, I'm going to build a forward chaining inference system using Common Lisp. This is going to be a challenge, but I'd like to do it in part to expand my knowledge, and also to build a free-software knowledge representation system that works well and is adaptable for various purposes.
This system requires very little in the way of outside packages,
only one, in fact, optima
, a very high-power pattern matching
library, used to implement the matching portion of the system.
(defpackage #:forward-chainer (:use #:cl #:optima #:fare-quasiquote-optima #:fare-quasiquote-readtable) (:export #:assert-knowledge #:assert-rule #:query-knowledge)) (in-package #:forward-chainer) (named-readtables:in-readtable :fare-quasiquote)
Two of the most important parts of the forward-chainer are the knowledge and rules database. Both of these are lists of lists, used to provide knowledge management.
(defvar *knowledge-database* '() "Knowledge Database, a list of lists.") (defvar *rules* '() "Rules list, each rule is a cons of a name and a rule object.")
assert-knowledge
Macro
(defmacro assert-knowledge ((name &rest arguments)) (let ((knowledge `'(,name ,@arguments))) `(pushnew ,knowledge *knowledge-database* :test #'equalp)))
remove-knowledge
Macro
(defmacro remove-knowledge ((name &rest arguments)) (let ((knowledge `'(,name ,@arguments))) `(delete ,knowledge *knowledge-database* :test #'equalp)))
assert-rule
Macro
(defmacro assert-rule ((name &rest arguments) matcher &rest actions) (declare (ignorable name arguments matcher actions)) )
query-knowledge
Macro
(defmacro query-knowledge ((name &rest arguments)) (let* ((match-variables (remove-if (lambda (var) (not (and (typep var 'symbol) (string= "?" (subseq (format nil "~a" var) 0 1))))) arguments)) (matcher `'(,name ,@arguments))) `(map 'list #'(lambda (knowledge) (match knowledge ',matcher)) ,*knowledge-database*)))
;;; forward-chainer.lisp <<package-definition>> ;; Begin main forward-chainer <<assert-knowledge>> <<remove-knowledge>> <<assert-rule>> <<query-knowledge>> <<knowledge-database>> ;;; End of "forward-chainer.lisp"
*RULES*