Gurugail Main/JESS
Main

JESS

Introduction

JESS, an expert system shell and scripting language written entirely in Sun Microsystem's Java language. JESS supports the development of rule-based expert systems which can be tightly coupled to code written in the powerful, portable Java language. JESS는 CLIPS의 superset으로 구성된 자바 버전의 전문가 시스템 쉘(shell) 또는 규칙 엔진임. 1955년에 처음 구성됨

JESS prompt

Jess has an interactive command-line interface. Just type java jess.Main (or java -classpath jess.jar jess.Main) to get a Jess> prompt. To execute a file of CLIPS code from the command prompt, use the batch command:

Jess> (batch examples/sticks.clp)
Who moves first (Computer: c Human: h)? 

What makes a good Jess application?

Jess can be used in two overlapping ways.

First, it can be a rule engine - a special kind of program that very efficiently applies rules to data. A rule-based program can have hundreds or even thousands of rules, and Jess will continually apply them to data in the form of a knowledge base.

Second, Jess language is also a general-purpose programing language, and furthermore, it can directly access all Java classes and libraries. For this reason, Jess is also frequently used as a dynamic scripting or rapid application development environment.

1. Jess vs. Prolog

In programming you should choose the right tool for the right job. Prolog and a Rete-based system like Jess are very different. The central concept in Prolog is backwards chaining: given the rules

human(Socrates). mortal(X) :- human(X).

you might be interested in knowing if mortal(Socrates) was true. Prolog uses the rules to find it by looking for human(Socrates). Note that if you forget the result and ask for it again, Prolog has to compute it again. The central concept in Jess, though, is forwards chaining. Here, you have

Jess> (assert (human Socrates))
Jess> (defrule mortal (human ?X) => (assert (mortal ?X)))
Jess> (watch facts)
Jess> (run)
==> f-1 (MAIN::mortal Socrates)
1

You don't specifically want to know (mortal Socrates) but rather you want to know what happens given that (human Socrates) is known. (mortal Socrates) is a result

The JESS Language

Basically strings in <angle-brackets> are some kind of data that must be supplied; things in [square brackets] are optional, things ending with + can appear one or more times, and things ending with * can appear zero or more times.

1. Basics

The atom or symbol is a core concept of the Jess language. Atoms are very much like identifiers in other languages. A Jess atom can contain letters, numbers, and the following punctuation: $*=+/<>_?#.

Jess atoms are case sensitive: foo, FOO and Foo are all different atoms.

Another fundamental unit of syntax in Jess is the list. A list always consists of an enclosing set of parentheses and zero or more atoms, numbers, strings, or other lists. The following are valid lists:

(+ 3 2) (a b c) ("Hello, World") () (deftemplate foo (slot bar))

2. Functions

Function calls in Jess are simply lists. Function calls use a prefix notation; a list whose head is an atom that is the name of an existing function can be a function call.

Jess> (+ 2 3)
5

3. Variables

Programming variables in Jess are atoms that begin with the question mark (?) character. A variable whose first character is instead a $ (for example, $?X) is a multivariable, which can refer to a special kind of list called a multifield. You assign to any variable using the bind function:

Jess> (bind ?x "The value")
"The value" 

4. Deffunctions

You can define your own functions using the deffunction construct. A deffunction construct looks like this:

Jess> (deffunction max (?a ?b)
(if (> ?a ?b) then
(return ?a)
else
(return ?b)))
TRUE

5. Java reflection

Among the list of functions above are a set that let you create and manipulate Java objects directly from Jess. Using them, you can do virtually anything you can do from Java code, except for defining new classes

Jess> (bind ?ht (new java.util.Hashtable))
<External-Address:java.util.Hashtable>
Jess> (call ?ht put "key1" "element1")
Jess> (call ?ht put "key2" "element2")
Jess> (call ?ht get "key1")
"element1"

6. The knowledge base

A rule-based system maintains a collection of knowledge called facts. In Jess, there are three kinds of facts: ordered facts, unordered facts, and definstance facts.

Ordered facts

Ordered facts are simply lists, where the first field (the head of the list) acts as a sort of category for the fact.

(shopping-list eggs milk bread)
(person "Bob Smith" Male 35)
(father-of danielle ejfried)

You can add ordered facts to the knowledge base using the assert function, and remove an individual fact from the knowledge base using the retract function.

Unordered facts

Ordered facts are useful, but they are unstructured. Sometimes (most of the time) you need a bit more organization. In object-oriented languages, objects have named fields in which data appears. Unordered facts offer this capability

(person (name "Bob Smith") (age 34) (gender Male))
(automobile (make Ford) (model Explorer) (year 1999))

before you can create unordered facts, you have to define the slots they have using the deftemplate construct: (deftemplate <deftemplate-name> [extends <classname>] [<doc-comment>] [(slot <slot-name> [(default | default-dynamic <value>)] [(type <typespec>))]*)

Jess> (deftemplate automobile
"A specific car."
(slot make)
(slot model)
(slot year (type INTEGER))
(slot color (default white)))

would allow you to define facts like this:

Jess> (assert (automobile (make Chrysler) (model LeBaron)
(year 1997)))
<Fact-0>

7. Defrules

Rules are defined in Jess using the defrule construct. A very simple rule looks like this

Jess> (defrule do-change-baby
"If baby is wet, change baby's diaper."
(baby-is-wet)
=>
(change-baby))

This rule has two parts, separated by the "=>" symbol (which you can read as "then".) The first part consists of the LHS pattern (baby-is-wet). The second part consists of the RHS action (change-baby). Although it's hard to tell due to the LISP-like syntax, the LHS of a rule consists of patterns which are used to match facts in the knowledge base, while the RHS contains function calls

8. Defqueries

The defquery construct lets you create a special kind of rule with no right-hand-side. While rules act spontaneously, queries are used to search the knowledge base under direct program control. A rule is activated once for each matching set of facts, while a query gives you a java.util.Iterator of all the matches. An example should make this clear. Suppose we have defined this query:

Jess> (defquery search
"Finds foo facts with a specified first field"
(declare (variables ?X))
(foo ?X ?Y))

9. Defmodules

typical rule-based system can easily include hundreds of rules, and a large one can contain many thousands. Developing such a complex system can be a difficult task, and preventing such a multitude of rules from interfering with one another can be hard too.

You can define a new module using the defmodule construct:

Jess> (defmodule WORK)
TRUE

Examples

1. Code examples

; is a comment

(bind ?x 100)
; x = 100

(deffunction max (?a ?b)
  (if (> ?a ?b) then ?a else ?b))

(deffacts myroom
   (furniture chair)
   (furniture table)
   (furniture bed)
)

(deftemplate car
   (slot color)
   (slot mileage)
   (slot value)
)

(assert (car (color red) (mileage 10000) (value 400)))

sample code

(clear)
(deftemplate blood-donor (slot name) (slot type))
(deffacts blood-bank ; put names & their types into working memory
      (blood-donor (name "Alice")(type "A"))
      (blood-donor (name "Agatha")(type "A"))
      (blood-donor (name "Bob")(type "B"))
      (blood-donor (name "Barbara")(type "B"))
      (blood-donor (name "Jess")(type "AB"))
      (blood-donor (name "Karen")(type "AB"))
      (blood-donor (name "Onan")(type "O"))
      (blood-donor (name "Osbert")(type "O"))
)

(defrule can-give-to-same-type-but-not-self ; handles A > A, B > B, O > O, AB > AB, but not N1 > N1
      (blood-donor (name ?name)(type ?type))
      (blood-donor (name ?name2)(type ?type2 &:(eq ?type ?type2) &: (neq ?name ?name2)  ))
      =>
      (printout t ?name " can give blood to " ?name2 crlf)
)

(defrule O-gives-to-others-but-not-itself ; O to O cover in above rule
      (blood-donor (name ?name)(type ?type &:(eq ?type "O")))
      (blood-donor (name ?name2)(type ?type2 &: (neq ?type ?type2) &: (neq ?name ?name2)  ))
      =>
      (printout t ?name " can give blood to " ?name2 crlf)
)

(defrule A-or-B-gives-to-AB ; case O gives to AB and AB gives to AB already dealt with
      (blood-donor (name ?name)(type ?type &:(or (eq ?type "A") (eq ?type "B" ))))
      (blood-donor (name ?name2)(type ?type2 &: (eq ?type2 "AB")  &: (neq ?name ?name2)  ))
      =>
      (printout t ?name " can give blood to " ?name2 crlf)
)

;(watch all)

(reset)
(run)

2. Example for simple game rule

Jess는 CLIPS 의 자바 버젼입니다. CLIPS와 물론 마찬가지로 Expert System을 구축하기 위한 Shell 입니다. 가령, 몬스터의 판단 기능을 Jess로 구축한다면,

Rule 1] 적이 있으면 공격하라 Rule 2] 나를 공격하면 적이다.

위 두 개의 Fact만 주어지면 Jess에서는 자동으로 "나를 공격하는 몬스터를 공격한다" 라는 판단 기능이 자동으로 추가되는 것입니다. 다시 말해, Rule에 의해 파생될 수 있는 모든 Rule을 처리할 수 있습니다. 전문가 시스템의 기능 중의 하나입니다.

아래는 JESS 부분의 간단한 소스입니다.

(defrule attack-if-enemy ""
         (enemy ?e)

         =>
         (assert (attack self ?e)))
(defrule enemy-if-attack-me ""
         (attack ?e self)
         =>
         (assert (enemy ?e)))

Demo Applet

클릭 (<- 간단한 데모 버젼입니다.)

Reference

http://en.wikipedia.org/wiki/Jess_(programming_language) http://www.jessrules.com/jess/index.shtml