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*