==== CLIPS - first contact====
CLIPS(C Language Integrated Production System) is an expert system tool. It is designed to facilitate the development of software to model human knowledge or expertise.
There are three ways to represent knowledge in CLIPS:
* rules - primarily intended for heuristic knowledge based on experience
* deffunctions and generic functions - primarily intended for procedural knowledge
* object-oriented programming - intended for procedural knowledge. It supports classes, message-handlers, abstraction, encapsulation, inheritance and polymorphism
You can develop software using only rules, only objects or both. CLIPS can be used as a standalone tool or called from other languages such as C, C++ or Java.
=== Let's start ===
To start CLIPS type in **clips** in console. You'll get a window with command prompt **CLIPS>**. This is where you type in your commands and programs.
== References ==
[[http://en.wikipedia.org/wiki/CLIPS|CLIPS:Wikipedia:en]]
[[http://clipsrules.sourceforge.net/|CLIPS - a tool for building Expert Systems]]
[[http://www.siliconvalleyone.com/clips.htm|NASA CLIPS rule-based language]]
[[http://rd13doc.cern.ch/Atlas/Notes/108/Note108-1.html|Expert system tool]]
Some important commands:
* **(load "prog.clp")** //load prog.clp// file to environment
* **(run)** execute a CLIPS program
* **(clear)** removes all rules and facts from memory
* **(reset)** removes all facts from memory but not rules
* **(exit)** exits CLIPS
You can create an empty file with ** *.clp** extension and there write all your rules. It is better solution than typing them in each time You start CLIPS. Remember that You can't put facts into ** *.clp** file in the same way as you can from the command prompt, so for now you’ll still enter them from command prompt. To save rules written in CLIPS command line write **(save "my-work.clp")**. It will save rules from memory in my-work.clp file.
=== Facts & rules ===
CLIPS operates by maintaining a list of facts and a set of rules operating on them. Fact is a basic informations created by asserting them onto the fact database:
CLIPS> (assert (colour blue))
CLIPS> (assert (colour red))
CLIPS provide basic arithmetical and math functions +, -, *, /, div, max, min, abs, float and integer:
CLIPS> (assert (number (sqrt (* (* 2 3) (+ 1 5)))))
CLIPS> (facts)
f-0 (number 6.0)
For a total of 1 fact.
It is possible to assert more facts at once:
(assert (colour red) (colour green) (colour white))
CLIPS> (facts)
f-0 (initial-fact)
f-1 (colour red)
f-2 (colour green)
f-3 (colour white)
For a total of 4 facts.
Other example:
CLIPS> (assert (name-of-dog "\"Beethoven\""))
CLIPS> (facts)
f-0 (name-of-dog ""Beethoven"")
For a total of 1 fact.
Note, that if You try to assert fact that is already in fact database you'll get the **false**. You can your fact database typing in **(facts)**:
CLIPS> (facts)
f-0 (colour blue)
f-1 (colour red)
For a total of 2 facts.
Fact may be removed from the fact database using the **retract** command. To retract fact you must specify the fact-index(not the fact itself). Fact-indices are not reused.
CLIPS> (retract 0)
CLIPS> (facts)
f-1 (colour red)
For a total of 1 fact.
Two useful commands allow You to save and load facts using a file. There are **(save-facts "my-facts-file")** and **(load-facts "my-facts-file")**
== Exercise ==
- What is a difference between two facts: (black) and (black nil)? Symbol **nil** means //nothing//(just like null in C).
=== ===
Facts only keeps information. To develop a program capable of some useful functions you need a set of rules. A rule is expressed in the form //IF something is true THEN do some actions//. General syntax of rule looks like:
(defrule rule-name "optional comment"
(pattern 1)
(pattern 2)
...
(pattern N)
=>
(action 1)
(action 2)
...
(action M))
If all patterns of a rule match facts, the rule is activated and put on the agenda. The agenda is a collection of activations which are those rules which match patters entities.
(defrule dog
(animal-is dog)
=>
(assert (dog_sound-is bark)))
The rule consists of three parts. In the sample rule, the first part **(defrule dog** gives the rule a unique name, the second part **(animal-is dog)** is a pattern of the rule (**IF**) and the part **(assert (sound-is bark))** is the actions of the rule(**THEN**). This rule means // if there is a fact **animal-is dog** on the facts database then assert another fact **(sound-is bark))** onto the fact database//.
Execute the sample rule:
CLIPS> (defrule dog
(animal-is dog)
=>
(assert (dog_sound-is bark)))
CLIPS> (rules)
dog
For a total of 1 defrule.
CLIPS> (facts)
f-0 (initial-fact)
For a total of 1 fact.
CLIPS> (assert (animal-is dog))
CLIPS> (facts)
f-0 (initial-fact)
f-1 (animal-is dog)
For a total of 2 facts.
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (animal-is dog)
f-2 (dog_sound-is bark)
For a total of 3 facts.
To get list of rules present in the system type **rules**. At the beginning there are no facts present. After asserting **animal-is duck** fact there is one fact in facts database. To trigger the rule type **(run)**. Then check the fact list again and you'll see that there is a new fact inferred by the rule. This is the power of rule-based programming.
Rules may have more than one pattern but then all must be satisfied for the action to be taken. The action part of rule can also have multiple actions.
Check another sample:
CLIPS> (defrule duck
(animal-is duck)
=>
(assert (sound-is quack))
(printout t "Asserted sound-is quack" crlf))
CLIPS> (defrule is-it-a-duck
(animal-has webbed-feet)
(animal-has feathers)
=>
(assert (animal-is duck))
(printout t "Asserted animal-is duck" crlf))
CLIPS> (assert(animal-has webbed-feet))
CLIPS> (assert (animal-has feathers))
CLIPS> (run)
Asserted animal-is duck
Asserted sound-is quack
Firstly, rule is-it-a-duck has asserted the fact (animal-is duck). This fact has then triggered rule duck, which has asserted the fact (sound-is quack). Very powerful systems can be built using this ability to chain rules.
Now try to develop more powerful program, for example an expert system to determine how a mobile robot should respond to a traffic light.
=== "Stop and go" example ===
Example rules for the red and green lights can be written as follows:
(defrule stop "if light is red wait for green"
(light red)
(not (light green))
=>
(printout t "Red Light, don't go!" crlf))
(defrule go "if there is green light go"
(light green)
(not (light red))
=>
(printout t "Green light, go!" crlf))
Now assert new fact **(light red)** or **(light green)** and run the program. There is used **(not)** function; it is predefined logical function of negation. The patterns
(light green)
(not (light red)
means that in fact database must exists (light green) fact and must NOT exists (light red) fact to fire the rule.
Think about other possibilities of beside the simple lights. Rewrite the program...
=== Alternative way to enter facts ===
It is possible to load facts from a file using keyword **deffacts**, for example:
(deffacts walk "some facts about \"stop and go \" sample"
(light green)
(status walking)
(walk-sign walk))
Now, after loading file to CLIPS it is needed to **(reset)** - causes facts from deffacts to be asserted.
The **undeffacts** command removes deffacts from the memory. To restore a deffacts statement after an **(undeffacts)** command, You must enter the statement again. In additional to facts it is possible to eliminate rules selectivity by using the **(undefrule)**. Other useful command are **list-deffacts** - lists the names of currently loaded deffacts, and **ppdeffacts** - print the facts stored in a deffacts.
CLIPS> (list-deffacts)
initial-fact
walk
For a total of 2 deffacts.
CLIPS> (ppdeffacts walk)
(deffacts MAIN::walk "some facts about \"stop and go \" sample"
(light green)
(status walking)
(walk-sign walk))
=== Debugging CLIPS programs ===
Basic tool for debugging programs is to watch asserting and retracting facts using **(watch facts)**:
CLIPS> (watch facts)
CLIPS> (assert (colour red))
==> f-1 (colour red)
CLIPS> (retract 1)
<== f-1 (colour red)
**==>** means that new fact is entering the memory, while **<==** means the fact is leaving memory.
Other helpful commands in debugging:
* (watch facts)
* (watch instances)
* (watch slots) *
* (watch rules)
* (watch activations)
* (watch messages) *
* (watch message-handlers) *
* (watch generic-functions)
* (watch methods) *
* (watch deffunctions)
* (watch compilation) ;on by default
* (watch statistics)
* (watch globals)
* (watch focus)
* (watch all) ;watch everything
* - used with objects
To turn off **watch** command use **unwatch**.