COMP 4200 - Expert Systems Lab Class 1 – Tasks and Solutions Start the CLIPS Interpreter. Familiarize yourself with the system. For a review of the central concepts of the CLIPS language, we go through the constructs in accordance with the course notes. You can use the CLIPS notes on the course web page for reference. We start with the Interpreter at the Command Line Level. Task 1 – assert, retract, facts, reset We enter some ordered facts into the system. The facts are: 1. (today is Tuesday) 2. (tomorrow is Wednesday) (assert (today is Tuesday)) (assert (tomorrow is Wednesday)) Check whether the facts have been entered properly. Retract the first fact. Check what’s left. Reset the system. Check’s what’s there now. (reset) then (facts) (retract 0) (facts) (clear) or clearClips in Execution Menu We use the CLIPS Editor in combination with the Interpreter. Task 2.1 – deftemplate, slots, editing, saving, loading a construct We first define a template for ‘person’ as seen in class, and create some facts based on this template. Define a template for ‘person’ including slots for name, age, gender. Then, add the definition of a factlist ‘people’ with 3 exemplars of ‘person’ to the file. (deftemplate person (slot age) (slot name) (slot gender) ) (deffacts people (person (age (person (age (person (age (person (age (person (age (person (age ) 20) 40) 24) 30) 42) 28) (name (name (name (name (name (name "Mike") (gender m)) "James") (gender m)) "Mark") (gender m)) "Silvia") (gender f)) "Susan") (gender f)) "John") (gender m)) Save everything and load the file into the interpreter. Reset the system. Check the facts you have. Save and load in File menu, (reset), (facts) Task 2.2 – deftemplate, multislots, types, allowed-values Now we want to enrich the template created in 2.1 by using multislots and TYPE information. Modify the definitions from 2.1 such that name is defined as multislot of type string, age is of type integer, and for gender we add (allowed-values male female) which explicitly declares ‘male’ and ‘female’ as the only allowed values for this slot. (deftemplate person (slot age (type INTEGER)) (multislot name (type STRING)) (slot gender (allowed-values f m)) ) ; f=female and m=male Modify the deffacts part accordingly and store the file under a new name. (deffacts people (person (age (person (age (person (age (person (age (person (age (person (age 20) 40) 24) 30) 42) 28) (name (name (name (name (name (name "Mike" "Moore") (gender m)) "James" "James") (gender m)) "Mark" "James") (gender m)) "Silvia" "James") (gender f)) "Susan" "Moore") (gender f)) "John" "Jones") (gender m)) ) Check in the interpreter whether the definition of the new facts worked properly. Save and load in File menu, (reset), (facts) Task 2.3 – defrule We write a very simple rule now called ‘find-<name>’ which finds a person with a specific name. Edit the rule in a new file. Specify the condition-pattern based on the deftemplate from above (2.1 or 2.2) and using the template-fact description (person (…) (…)) where (…) specifies the slot constraint, e.g. (name “Berta”). Note: you need only specify the template-name and the slots you want for the pattern match. First, we want to find a specific name. (defrule find-MikeMoore (person (name "Mike" "Moore")) => (printout t "Found Mike Moore" crlf) ) You can also make it a little more complex if you search just for the first or second name, and leave the other one open and have it bound during pattern matching to a variable. (defrule find-Moore (person (name ?first-name "Moore") ) => (printout t "Found " ?first-name " Moore" crlf) ) Next, we want to find all people above a certain age – for this you add a test function. For each case, give some printout of the result. (defrule pub-check "also called the older-than-twenty-one rule" (person (name ?first-name ?last-name) (age ?age)) (test (> ?age 21)) => (printout t ?first-name " " ?last-name " is " ?age " years old and thus over twenty-one." crlf) ) You can do this in yet a different way specifying the age-constraint as a constraint on the field-value, by attaching a predicate-expression directly to the slot (see below and CLIPS Intro addition1): (defrule pub-check2 "also called the older-than-twenty-one rule" (person (name ?first-name ?last-name) (age ?age&:(> ?age 21))) => (printout t ?first-name " " ?last-name " is " ?age " years old and thus over twenty-one." crlf) ) Task 3.1 – deftemplate, Browse-Menu, Execution Menu We want to define a template and create some facts based on this template in the Editor. The template will describe courses as shown in faculty calendars etc. Thus, we call the template ‘course’ and define it with the following features: 1. course number (INTEGER or NUMBER) 2. course title (STRING) 3. instructor’s last name (STRING) you can define a multislot with first-name and last-name instead 4. days as multislot (STRING) you can add an allowed-value declaration Edit the template in the editor and save it as file. (deftemplate course (slot course-number (type INTEGER)) (slot course-title (type STRING)) (slot instructor (type STRING)) (multislot days (type STRING)(allowed-values "M" "Tu" "W" "Th" "F")) ) Load the file into the CLIPS Interpreter. What happens? – If the construct is syntactically correct, the Interpreter should return at some point ‘true’. If not, you get an error message. Then, go back into the Editor, make changes, save and load the file again. When the Interpreter gives its okay, you can check the template in the Browse menu. Use the PrettyPrint (PPRINT) function. Since we have added specific type information to the template, make sure that the Constraint Checking options are checked accordingly (Execute Menu). Task 3.2 – deffacts, sequence of definitions We want to create facts on the basis of this template. Either in the same file AFTER the deftemplate, or in a new file, create a factlist called ‘courses’ in which you define four courses as facts. Save the file and load it into the Interpreter. If you have two files, you must load the template-definition first: The CLIPS system needs the definition of the template in order to create the factlist. (deffacts courses (course (course-number 1) (course-title "course (instructor "Jim")(days "M" "W" "F")) (course (course-number 2) (course-title "course (instructor "Jane")(days "M" "W" "F")) (course (course-number 3) (course-title "course (instructor "Jim")(days "Tu" "Th")) (course (course-number 4) (course-title "course (instructor "John")(days "M" "W" "F")) (course (course-number 5) (course-title "course (instructor "Jim")(days "Tu" "Th")) ) 1") 2") 3") 4") 5") When the file is loaded properly, reset the system. Check whether the facts you have defined for the courses are available. If not: Did you do a reset? If that doesn’t help, check your file again. Are parentheses properly set? Is the syntax correct? If you cannot figure it out: Ask your neighbor. Ask the instructor. Task 3.3 – modify, fact-index We work on the Command Line Level for this task. The Department has decided to substitute one of its courses with a new one. That means that the old course number must be substituted with the new course number. Modify the respective fact, by substituting the old course number with the new one. Check the facts. Everything’s alright? Remember: You have to give the specific fact-number here (command level) and just enter the new slot with slot-name and slot-value. CLIPS> (clear) CLIPS> (load "C:/74.420 (2003)/Lab/course-facts.CLP") Defining deftemplate: course Defining deffacts: courses TRUE CLIPS> (reset) ==> f-0 (initial-fact) ==> f-1 (course (number 1) (instructor "Jim")) ==> f-2 (course (number 2) (instructor "Jane")) ==> f-3 (course (number 3) (instructor "Jim")) ==> f-4 (course (number 4) (instructor "John")) ==> f-5 (course (number 5) (instructor "Jim")) CLIPS> (modify 2 (instructor "Jamie")) <== f-2 (course (number 2) (instructor "Jane")) ==> f-6 (course (number 2) (instructor "Jamie")) <Fact-6> CLIPS> (facts) f-0 (initial-fact) f-1 (course (number 1) (instructor "Jim")) f-3 (course (number 3) (instructor "Jim")) f-4 (course (number 4) (instructor "John")) f-5 (course (number 5) (instructor "Jim")) f-6 (course (number 2) (instructor "Jamie")) For a total of 6 facts. Task 3.4 – defrule, field- and fact-variables, <- binding Now you will write a rule using the editor. One of the professors is leaving the University and is replaced with a new one. That means for every course which was supposed to be taught by the leaving prof, it must now be assigned to the new prof. The rule should check the course-facts and match with any fact in which the leaving professor is instructor and his/her name must be replaced with the new professor’s name. Remember that you only have to specify the template-name and the slots which you want to use for the Pattern Matching. (defrule substitute-instructor "Replace the instructor Jim with Joe" ?Jim's-Course <- (course (instructor "Jim")) => (modify ?Jim's-Course (instructor "Joe")) ) Note: Watch the sophisticated naming of the variable: ?Jim's-Course Write the rule in the Editor, save it and load it into the interpreter (after having loaded the template and facts for courses). If you do not get an error message, check the Watch-options for displaying facts, activations, and firings. Let it run. Did it work? If not, check whether your facts are there. Did the rule get activated at all? If not, your condition pattern must be odd. If it does get activated but doesn’t do what it should, check the modify-function in the action part of the rule. If you cannot figure it out, scream for help. Task 3.5 Now modify your fact list such that the leaving prof is teaching three courses. Use the editor to change the file with the deffacts construct. Load your facts and the rule and let it run (don’t forget reset in between). Observe in which sequence the rule is activated and then fires for the different matching facts. Describe the ‘conflict resolution strategy’ which CLIPS performs in this case. CLIPS> (clear) CLIPS> (load "H:/74.420 (2003)/Lab/course-facts-1.CLP") Defining deftemplate: course Defining deffacts: courses TRUE CLIPS> (reset) ==> f-0 (initial-fact) ==> f-1 (course (course-number 1) (course-title "course 1") (instructor "Jim") (days "M" "W" "F")) ==> f-2 (course (course-number 2) (course-title "course 2") (instructor "Jane") (days "M" "W" "F")) ==> f-3 (course (course-number 3) (course-title "course 3") (instructor "Jim") (days "Tu" "Th")) ==> f-4 (course (course-number 4) (course-title "course 4") (instructor "John") (days "M" "W" "F")) ==> f-5 (course (course-number 5) (course-title "course 5") (instructor "Jim") (days "Tu" "Th")) CLIPS> (load "H:/74.420 (2003)/Lab/course-rule-2.CLP") Defining defrule: substitute-instructor +j ==> Activation 0 substitute-instructor: f-1 ==> Activation 0 substitute-instructor: f-3 ==> Activation 0 substitute-instructor: f-5 TRUE CLIPS> (run) FIRE 1 substitute-instructor: f-5 <== f-5 (course (course-number 5) (course-title "course 5") (instructor "Jim") (days "Tu" "Th")) ==> f-6 (course (course-number 5) (course-title "course 5") (instructor "Joe") (days "Tu" "Th")) FIRE 2 substitute-instructor: f-3 <== f-3 (course (course-number 3) (course-title "course 3") (instructor "Jim") (days "Tu" "Th")) ==> f-7 (course (course-number 3) (course-title "course 3") (instructor "Joe") (days "Tu" "Th")) FIRE 3 substitute-instructor: f-1 <== f-1 (course (course-number 1) (course-title "course 1") (instructor "Jim") (days "M" "W" "F")) ==> f-8 (course (course-number 1) (course-title "course 1") (instructor "Joe") (days "M" "W" "F")) CLIPS> (facts) f-0 (initial-fact) f-2 (course (course-number 2) (course-title "course 2") (instructor "Jane") (days "M" "W" "F")) f-4 (course (course-number 4) (course-title "course 4") (instructor "John") (days "M" "W" "F")) f-6 (course (course-number 5) (course-title "course 5") (instructor "Joe") (days "Tu" "Th")) f-7 (course (course-number 3) (course-title "course 3") (instructor "Joe") (days "Tu" "Th")) f-8 (course (course-number 1) (course-title "course 1") (instructor "Joe") (days "M" "W" "F")) For a total of 6 facts. CLIPS> (dribble-off) Tip: CLIPS will automatically write the interpreter dialogue into a file called 'dribble.txt' when you select 'dribble-on' in the File Menu.