History of CLIPS (½) NASA. Johnson Space Center. AIS developed LISP-based prototype ES applications. Failure to provide ES technology within NASA due to LISP: Code, Compilers, and Cost. A shift to a conventional language, such as C, would solve problems. Tool vendors started converting: Costly. Time consuming. Restrictions on some machines
History of CLIPS (2/2) AIS decided to build its own C-based ES tool. They developed a prototype version in 2 months: C Language Integrated Production System was born in Spring The tool was made compatible with LISP-based ES being developed by AIS then: OPS5 (first production system using Rete) and ART. CLIPS was a feasible project in terms of ES construction and as a replacement tool. Another year of development before CLIPS was made available outside NASA. Summer 1986.
Users & Platforms CLIPS is used by the Government, Industry, and Academia. Download it from The Official CLIPS Website. It can be ported to any system with an ANSI C Compiler. Windows 95/98/NT/XP MS-DOS MacOS UNIX (ssh alpha.cs.concordia.ca)
Programming Paradigms in CLIPS Forward Chaining Rule-based Language C Language Integrated Production System : States, Rules, Actions. IF THEN Control Mechanism avoids reaching deadlock. Reasoning from facts to conclusions. Procedural Programming COOL: CLIPS Object Oriented Language
Rule-based ES Architecture (½)
Rule-based ES Architecture (2/2) Acquire Knowledge. Set of rules with the following structure: P1 & P2 … & Pn => A1 & A2 &.. & An. Knowledge is stored in the Knowledge Base also called the Rule Base. It will contain the operators which transform the problem state into a solution. The Fact Base, also called Working Memory, represents the initial state of the problem. Only asserted facts are found in the Fact Base. The Inference Engine works in a recognize-act cycle: 1) It Matches the facts in the FB against the rules in the KB. 2) It then Chooses which rule to fire. 3) And finally Executes the actions associated with that rule. Explanation Facility stores which rules have been fired over which facts.
Facts: assert & retract (1/7) To invoke the CLIPS interpreter: clips alpha.miche_kh % clips CLIPS (V /01/98) To assert a fact directly in the Fact-base: (assert *) CLIPS> (assert (dinner is ready)) CLIPS> (assert (oven is off)) To list the facts in the Fact-base: (facts) CLIPS> (facts) f-0(dinner is ready) f-1(oven is off) For a total of 2 facts. To remove one or more facts from the fact base: (retract *) CLIPS> (retract 1) CLIPS> (facts) f-0(dinner is ready) For a total of 1 fact.
Facts: assert & retract (2/7) To assert several facts in one command, also: (assert *) CLIPS> (assert (dinner is ready) (oven is off) ) CLIPS> (facts) f-0(dinner is ready) f-1(oven is off) For a total of 2 facts. To remove several facts in one command, also: (retract *) CLIPS> (retract 0 1) CLIPS> (facts) CLIPS> assert & retract manipulate the Fact-Base via the part of the rule.
Facts: deffacts & reset (3/7) To define a potential set of facts: (deffacts deffacts-name [ ] *) CLIPS> (deffacts rr-facts (name roger-rabbit) (ears long) ) CLIPS> (facts) CLIPS> The Fact-Base is empty because those “potential” facts have not been asserted yet. To promote them from their potential state to the Fact-base: (reset) CLIPS> (reset) CLIPS> (facts) f-0(initial-fact) f-1(name roger-rabbit) f-2(ears long) For a total of 3 facts. reset clears the Fact-Base from all existing facts and inserts the facts associated with all currently defined sets of facts It is also responsible for adding the single f-0 (initial-fact) system-defined fact.
Facts: clear & run (4/7) To explicitly clear the Fact-Base of all facts: (clear) CLIPS> (clear) CLIPS> (facts) CLIPS> To load your.clp: (load “file-name.clp”) Clearing the Fact-Base here is optional since reset takes care of that. To remove dynamic information from memory and reset the AGENDA: (reset) To match active facts against the rules in KB and execute the : (run) To exit CLIPS: (exit)
Facts: fields (5/7) Fields: Data-types in CLIPS 1. FLOAT: [+/-] *[. *][e|E[+/-] *] e.g e INTEGER: [+/-] * e.g SYMBOL: [ * ;optional use of the restricted character < 4. STRING: “ *” e.g. “<|&( );” 1. CLIPS IS Case-Sensitive! 1. Words cannot start with any of the following: < | & $ ? + - ( ) ; Or contain any of the following: < | & ( ) ; 1. More on Fields and examples of Valid Expressions and Valid Facts, in Alina and Serguei's tutorial, on the course web page.
Facts: deftemplates (6/7) Templates resemble simple records. To define a Template: (deftemplate [ ] (slot (type ) [(default )])* ) CLIPS> (deftemplate tutor “past tutors for Expert Systems” (slot name (type STRING)) (slot year (type NUMBER) (default 2002)) ) CLIPS>(deffacts tutor (tutor (name “Serguei”)) (tutor (name “Alina”) (year 2001)) ) CLIPS> (reset) CLIPS> (assert (tutor (name “Michelle”) (year 2003)) 1. Now, you count a total of 4 facts. Remember that if you would have asserted Michelle 2003 (f-1) and then reset you would loose f-1.
Facts: modify & duplicate (7/7) CLIPS> (facts) f-0(initial fact) f-1(tutor (name “Serguei) (year 2003)) f-2(tutor (name “Alina”) (year 2001)) f-3(tutor (name “Michelle”) (year 2003)) For a total of 4 facts. To modify a fact: (modify *) CLIPS> (modify 1 (year 2002)) To duplicate a fact: (duplicate *) CLIPS> (duplicate 3 (year 2001)) CLIPS> (facts) f-1 (tutor (name “Serguei”) (year 2002) f-3 (tutor (name “Michelle) (year 2003) f-4 (tutor (name “Michelle”) (year 2001)) Modify edits the original fact while duplicate edits a copy of the original. Note that you cannot have two identical copies of one fact i.e. (duplicate 3 (year 2003)) or (duplicate 3) or (duplicate 3 (name “Michelle”) (year 2003)) do not work.
Rules: defrule (1/8) The general syntax of a rule is similar to IF THEN. A rule can have a priority, also called salience. The higher the salience, the more priority one rule has over another. The salience of a rule is an integer that ranges between [-10,000, +10,000]. If the salience is not explicitly declared in the rule’s construct, then the salience of the rule is set to the default value 0. To define a rule: (defrule [ ] [ ] * => * ) CLIPS> (defrule start (initial fact) => (printout t “Silly World!” crlf) ) CLIPS> (reset) CLIPS> (watch rules) ;This tells you which rule fires. CLIPS> (watch facts) ;This tells you which fact has been asserted. CLIPS> (dribble-on “dribble.clp”) CLIPS> (run) 1. Once the rule fires, it is taken off the AGENDA and a second run won’t output “Silly World” again unless you (refresh start). This is called REFRACTION.
Rules: conflict (2/8) RULE-BASE: R1: f1 & f2 & f3 => A1 R2: f2 =>A1 & A2 R3: f1 & f2 => A3 FACT-BASE: F1, F2, and F3 are asserted in their order of appearance. AGENDA: R2, R3, and R1 are put on the AGENDA in this order and the top most rule fires. However, this is the naïve case. There are guidelines to follow when ordering the rules on the stack. (defrule chores “Things to do on Sunday” (salience 10) (today is Sunday) (weather is warm) => (assert (wash car)) (assert (chop wood)) ) (defrule fun “Better things to do on Sunday” (salience 100) (today is Sunday) (weather is warm) => (assert (drink beer)) (assert (play guitar)) )
Rules: conflict resolution (3/8) In CLIPS, when rules are placed on the AGENDA, their instantiations are ordered according to one of seven conflict-resolution strategies which are based on one or more of the following mechanisms: recency: prefers rules which use more recent data specificity: prefers those that have more premises and are harder to satisfy refraction: once a rule is fired for a certain set of facts, it is taken off the AGENDA. This is referred to as refraction and avoids continuous looping over the same rule. To force the rule to fire again: (refresh ) Rules with higher salience are allowed to stay at the top of the stack no matter when they were added. So, you have to look at both, strategy and salience. Consider the previous set of rules and asserted facts. The topmost rule on the AGENDA fires. But how are the rules stored on the AGENDA in the first place? By Salience: R2 R3 R1. By Recency: R1 R2 R3 (same salience). R2 R1 R3 (different salience). By Specificity: R2 R1 R3 (different salience). R1 R3 R2 (same salience).
Rules: conflict resolution example (4/8) To set one of the following strategies: (set-strategy ) Depth – Rules activated by new data are placed above rules activated by old data. Breadth – Rules activated by new data are placed below rules activated by old data. Simplicity – Rules activated by new data are placed above all activations of rules with the same or higher specificity. Complexity -- Rules activated by new data are placed above all activations of rules with the same or lower specificity. LEX – Apply refraction and then sort rules by recency. Recency tie? Apply specificity. MEA – Choose instantiation(s) with newest match to first pattern. Tie? Apply LEX to remaining matches. Random Assume you have the following set of rules (same salience) on the AGENDA: Rule 5: F4 Rule 3: F1 F2 F3 Rule 1: F3 F4 Rule 2: F1 F3 F4 Rule 4: F1 F2 Depth: R5 R1 R2 R3 R4 MEA: R5 R1 R2 R3 R4
Rules: variables & wildcards (5/8) Variables: Must begin with a ? prefix. e.g. ?mood Single-field: ? * Match to facts in KB & bound consistently within a single rule Multi-field: $? * It is possible that $? is assigned to nothing. (do carwash on Sunday) (do ? ? Sunday) (do ? on ?) (do ? on ?when) (do $?) (do $? Sunday) (do ?chore $?when) (mood $? happy $?) (mood ? happy) (mood happy sad angry upset) (mood happy sad) (mood angry happy) (mood happy)
Rules: binding (6/8) CLIPS> (defrule pick-a-chore “allocating chores to days” (today is ?day) (chore is ?job) => (assert (do ?job on ?day)) ) CLIPS> (deffacts today (today is Sunday) (chore is carwash) ) Reset adds f-0, f-1, and f-2 to the Fact-Base. Run matches ?day with Sunday, ?job with carwash, and allows rule “pick-a-chore” to fire. As a result, f-4 (do carwash on Sunday) is asserted. EXAMPLE IN JACKSON’S TEXTBOOK, PAGE 466. (defrule drop-a-chore “allocating chores to days” (today is ?day) ?chore <- (do ?job on ?day) => (printout t chore is ?chore job is ?job day is ?day crlf) (retract ?chore) ) This prints to screen: chore is carwash Sunday If all facts in the Fact-Base are to be retracted: (retract *)
Rules: logical and (7/8) (defrule candidate-qualifies “IBM group is recruiting” (quality creative) (math-background strong) (programming-skills excellent) (team-work effective) => (assert (IBM hire-candidate)) ) AND: ALL premises on the LHS must be met in order to execute the action.
Rules: logical or + math (8/9) (defrule candidate-qualifies-1 (quality creative) => (assert (IBM hire-candidate)) ) (defrule candidate-qualifies-2 (math-background strong) => (assert (IBM hire-candidate)) ) (defrule candidate-qualifies-3 (programming-skills excellent) => (assert (IBM hire-candidate)) ) (defrule candidate-qualifies-4 (team-work effective) => (assert (IBM hire-candidate)) ) Or: Combine the rules into one if they have the same. Note that matching one fact in the combined rule will be sufficient to execute the action. (defrule candidate-qualifies (or (quality creative) (math-background strong) (programming-skills excellent | good) (team-work effective) ) => (assert (IBM hire-candidate)) ) MATH: Notice how the OR comes before the two arguments, rather than between them. This is called the prefix notation and all CLIPS operators work this way. Instead of writing in infix (5 + &), you write it in prefix (+ 5 7). CLIPS> (+ 10 (- (* 4 19) (/ 35 12))) CLIPS> (- (+ 10 (* 4 19)) (/ 35 12)) Both expressions evaluate to: 10+4*19-35/12
Rules: logical not (9/9) NOT: Negates a single pattern. (defrule candidate-qualifies (math-background ?level & strong | high) (programming-skills excellent) (not (team-work ~effective)) => (assert (IBM hire-candidate)) )
Built-in Functions The LHS does not necessarily only consist of a set of facts. We could have a boolean test: (test ) Predicate Functions return a value: True or False and, not, or ( ) ( | |>=> ) Test the type of a field: numberp stringp wordp integerp evenp oddp (test numberp ) (test (stringp name))
I/O (defrule Example (initial-fact) (test (<= 5 8)) => (printout t “What is your name?” crlf) (bind ?name (read)) (printout t ?name “ Would you like to go now? (y/n)” crlf ) (bind ?answer (read)) (if (or (eq ?answer yes) (eq ?answer y)) then (halt) else (printout t “Aren't you hungry?”) ) You can also use (assert (your-name [=] (read))) Again note that unless all premises on the LHS of a rule are satisfied, the rule will not fire.
Halting CLIPS While there are facts in the FACT-Base and rules on the AGENDA, CLIPS keeps looping and looking for rules to fire. Unless there are no more rules to fire, the program will not stop. You might want to define a rule that stops the execution once it has reached the goal: (defrule found-answer (…) ; test if answer is_found => (halt) )