home *** CD-ROM | disk | FTP | other *** search
- Chapter 4 Variable Interests
-
-
-
-
- The type of rules you've seen so far illustrate simple pattern matching of
- conditional elements to facts. In this chapter you'll learn very
- powerful ways to match and manipulate facts.
-
-
- Let's Get Variable
-
-
- Just as with other programming languages, CLIPS has variables available to
- store values. Variables give the programmer a powerful tool that
- is indispensible in many applications.
- Variables in CLIPS are always written in the syntax of a question mark
- followed by a symbolic atom name. Some examples of variables are as
- follows.
-
- ?x
- ?sensor
- ?valve
- ?noun
- ?color
-
- Be sure there is no space between the question mark and symbolic atom name or
- else CLIPS will misinterpret it.
- Before a variable can be used, it should be assigned a value. As an example
- of a case where it's not assigned, enter the following rule which
- has variable ?x in the (printout).
-
- (defrule test
- (initial-fact)
- =>
- (printout ?x crlf))
-
- In the above example, notice how initial-fact is used to trigger the rule.
- This is convenient since you can assert initial-fact by simply
- doing a (reset), which saves you the trouble of asserting initial-fact.
- When you run the program, the output will be
-
- Variable x not found
- number
-
- CLIPS gives an error message because it cannot find a value which has been
- bound to ?x. The terms bound and bind are used to describe the
- assignment of a value to a variable. Variables can be bound to symbolic atoms
- or numbers. Although no value was bound to ?x in the previous
- example, CLIPS returned a symbolic atom called "number". The atom "number" is
- meaningless and you should not rely on its assignment to unassigned
- variables in future releases of CLIPS.
-
-
- Be Assertive
-
-
- One common use of variables is to bind a value on the LHS and then assert the
- bound variable on the RHS. For example, enter
-
- (defrule make-quack
- (duck ?sound)
- =>
- (assert (?sound)))
-
- Now assert (duck quack) and then (run) the program. Check the facts and you'll
- see that the rule has produced (quack) because the variable ?sound
- was bound to (quack).
- Of course, you can also use a variable more than once. For example, enter
- the following. Also, be sure to do a (reset) and assert (duck
- quack) again.
-
- (defrule make-quack
- (duck ?sound)
- =>
- (assert (?sound ?sound)))
-
- When the rule fires, it will produce (quack quack) since the variable ?sound is
- used twice.
-
-
- What The Duck Said
-
-
- Variables are also commonly used in (printout), as in
-
- (defrule make-quack
- (duck ?sound)
- =>
- (printout "The duck said " ?sound crlf))
-
- Enter this rule and run to find out what the duck said. How would you modify
- the rule to put double quotes around quack in the output?
-
-
- The Happy Bachelor
-
-
- Retraction is very useful in expert systems and is usually done on the RHS.
- Before a fact can be retracted, it must be specified to CLIPS.
- To retract a fact from a rule, the fact address must first be bound to a
- variable on the LHS.
- There is a big difference between binding a variable to the contents of a
- fact and binding a variable to the address of a fact. In the examples
- you've seen, such as (duck ?sound), a variable was bound to the contents of a
- fact. That is, ?sound was bound to quack. However, if you want
- to remove the fact whose contents are (duck quack), you must tell CLIPS the
- address of the fact to be retracted.
- The address of the fact is specified using the left arrow operator, "<-".
- To make this operator, just type a "<" symbol followed by a "-".
- As an example of fact retraction from a rule, enter the following example.
-
- (defrule marriage
- ?bachelor <- (Rey)
- =>
- (printout "Rey is now happily married" crlf)
- (retract ?bachelor))
-
- Assert the fact (Rey) and then run. After execution, check the fact-list and
- you'll see no (Rey) since it has been retracted. The conditional
- element in the rule assigns the address of (Rey) to the variable ?bachelor.
- The (retract) then removes the fact (Rey) whose address was assigned
- to ?bachelor.
- Variables can be used to pick up a fact content at the same time as an
- address. For example
-
- (defrule marriage
- ?bachelor <- (?name)
- =>
- (printout ?name " is now happily married" crlf)
- (retract ?bachelor))
-
- The above rule will fire when ?name is assigned to any fact. Enter the rule
- and then assert the facts (duck), (Marlon), and (Gary). When
- you run, you'll see the three happily married ex-bachelors. Notice how the
- rule fired on all facts which matched the conditional element (?name).
-
-
- John Smith's Marriage
-
-
- Will the marriage rule fire on a fact with two symbolic atoms like (John
- Smith)? Try it and see. The rule will not fire because there are two
- atoms in (John Smith) while the conditional element specifies one atom to be
- matched to (?name).
- So how do we get John Smith married? One approach you might try is the
- following, in which two variables called ?name are specified to match
- the two atoms in (John Smith).
-
- (defrule marriage
- ?bachelor <- (?name ?name)
- =>
- (printout ?name ?name" is now happily married" crlf)
- (retract ?bachelor))
-
- However, this rule won't fire on (John Smith) because the conditional element
- (?name ?name) specifies that the two atoms must be the same since
- the same variable ?name is used for both atoms.
- The way to get John Smith married is to use two different variables, as
- follows.
-
- (defrule marriage
- ?bachelor <- (?first ?last)
- =>
- (printout ?first ?last " is now happily married" crlf)
- (retract ?bachelor))
-
- Enter this rule and then assert (John Smith). When you run, you'll see that
- John Smith finally gets married.
- Suppose John has a brother whose first name is Smith (their parents liked
- simple names). Will this rule make Smith Smith get married too?
- Assert (Smith Smith) and run again. You'll see that there will be a double
- wedding indeed.
- Notice that the conditional element (?first ?last) matched any two symbolic
- atoms while (?name ?name) required that the two atoms were the
- same.
-
-
- How To Make John Very, Very Happy
-
-
- The (assert) can be used with (retract) to produce some interesting effects.
- As a simple example, suppose we wanted to make John not just happy,
- but very, very happy. The following program shows how John can become very,
- very happy. Enter it and assert (John Smith). Be sure to save
- the program before you run it.
-
-
- (defrule ecstatic
- ?bachelor <- (?first ?last)
- =>
- (printout ?first " " ?last " is a happy man" crlf)
- (retract ?bachelor)
- (assert (?first ?last)))
-
- The program executes an infinite loop since it asserts a new (John Smith)
- after retracting the old ?bachelor. Note that to make a new (John
- Smith) you must assert the individual atoms such as ?first and ?second. CLIPS
- is not designed to allow assertions of entire facts with statements
- like (assert (?bachelor)). After the new (John Smith) is asserted, the rule
- then fires on the new (John Smith).
- The only way to stop an infinite loop like this is by interrupting CLIPS.
- Use a Control C or appropriate interrupt command for your computer.
- You'll have to restart CLIPS again.
- Will the program still produce an infinite loop if you remove the (retract)
- statement? The answer is no since the new attempted assertions
- are duplicates of the fact in memory.
-
-
- Who's Eligible
-
-
- Rather than having to specify a certain fact to trigger a rule, you can just
- specify a general conditional element using a wildcard. For example,
- suppose you're running a dating service and a woman specifies that she only
- dates men whose first name is John. There are really two criteria
- in this specification since there is an implication that the man must have
- more than one name. So a plain (John) will not do because there
- is only one name in the fact.
- This type of situation in which only part of the fact is specified is very
- common and very important. To solve this problem, a wildcard can
- be used to fire a rule to print out the John's.
- The simplest form of wildcard is called a single-field wildcard and is shown
- by a question mark, "?". A single-field wildcard stands for
- one atom. The following rule and deffacts show how a wildcard can be used.
- Enter and run.
-
- (defrule eligible
- (John ?)
- =>
- (printout "There is an eligible John" crlf))
-
- (deffacts bachelors
- (Tom)
- (John)
- (John Smith)
- (John Henry)
- (John Henry Smith))
-
- The conditional element includes a wildcard to indicate that John's last
- name is not important. So long as his first name is John, the rule
- will be satisfied and fire. Because the wildcard is in the second field, that
- is, the position of the second atom of a fact, only facts of
- two atoms can possibly satisfy the rule. In other words, only John's with
- exactly two names need apply.
- Suppose you want to specify John's with exactly three names? All you'd have
- to do is write a conditional element like
-
- (John ? ?)
-
- or if only persons with three names whose middle name was John
-
- (? John ?)
-
- or if only the last name was John
-
- (? ? John)
-
- Another interesting possibility is if the the John must be the first name,
- but only those with two or three names are acceptable. One way
- of solving this problem is to write two rules. For example
-
- (defrule eligible
- (John ?)
- =>
- (printout "There is an eligible John" crlf))
-
- (defrule eligible-three-names
- (John ? ?)
- =>
- (printout "There is an eligible John" crlf))
-
- Enter and run this and you'll see that both the John's with two and three names
- are printed.
-
-
- Going Wild
-
-
- Rather than writing separate rules to handle each field, it's much easier to
- use the multi-field wildcard. The multi-field wildcard is a dollar
- sign followed by a question mark, "$?", and represents zero or more occurences
- of an atom. The two rules for eligibility can now be written
- in a single rule as follows. Also shown is the deffacts of eligible bachelors.
-
- (defrule eligible
- (John $?)
- =>
- (printout "There is an eligible John" crlf))
-
- (deffacts bachelors
- (Tom)
- (John)
- (John Smith)
- (John Henry)
- (John Henry Smith))
-
- When you enter and run, you'll see that the rule fires four times since there
- are four (John) facts.
- Wildcards have another important use because they can be attached to a
- symbolic atom to create a variable such as ?x, $?x, ?name, $?name.
- You've already seen examples of single-field variables at the beginning of
- this chapter. Now you can understand why the variables had a "?"
- in front. The attached variable will be equated to either a single-field
- wildcard if only the "?" is used or a multi-field wildcard, "$?",
- if that is used.
- As example of a multi-field variable, the following version of the rule also
- prints out the name of the matching fact because a variable is
- equated to the name that matches.
-
- (defrule eligible
- (John $?name)
- =>
- (printout "There is an eligible John " $?name crlf))
-
- When you enter and run, you'll see the names of all the eligible John's. The
- multi-field wildcard takes care of any number of atoms. No matter
- how long John's other names are, the multi-field wildcard will take care of it.
- What do you think the matches would be if the conditional element was
- ($?name) alone? Try it and you'll see that the rule matches to every
- fact, even (Tom).
- Suppose you wanted a match of all people who had a John somewhere in their
- name, not necessarily as their first name. Notice that this requirement
- is not the same as in the previous rule. Some possible matches would be
-
- (John)
- (Tom John)
- (Tom Henry John)
- (Tom John Henry)
- (Tom Henry John Smith)
-
- The following version of the rule would match all facts with a John in them
- and print out the names.
-
- (defrule eligible
- ($?first John $?last)
- =>
- (printout "There is an eligible " $?first " John " $?last crlf))
-
- Enter and run this rule and you'll see all the matching John's. The
- conditional element matches any names that have a John anywhere in them.
- Single and multi-field wildcards can be combined. For example, the
- conditional element
-
- (? $? John ?)
-
- means that the first and last names can be anything, and that the name just
- before the last must be John. For example,
-
- Name Match
- (John) No
- (John Smith) No
- (Tom John Smith) Yes
- (Tom John Henry Smith) No
- (Tom Henry John Smith) Yes
-
- Note that the "$?" can match zero or more occurences of an atom. Matching zero
- occurences means that there can be a match with no atom. So
- a conditional element like ($?name) will match any fact. In contrast, the "?"
- requires an atom to match.
- .PA
- Problems
-
-
- 1. A factory has different bars in stock. The ID and dimensions of the stock
- are given as follows.
-
- ID Length Width Height
- Fe-1 10 10 10
- Cu-2 20 10 10
- Cu-3 20 10 20
- Pt-4 10 20 10
- Fe-5 30 30 10
- Fe-6 30 20 10
- Fe-7 10 30 20
- Cu-8 10 20 30
- Pt-9 30 20 10
- Pt-10 20 20 20
- Table 4.1
-
- Write a program that will classify the bar stock according to the following
- definitions.
-
- square cross section - length=width
- square side - width=height
- cubes - length=width=height
-
- The program should print out the stock ID and all the dimensions of stock that
- matches the definitions. Objects may be in more than one category.
- For example, a cube will also be listed as having square cross section and
- square side.
- The priority of printing should be all the cubes, then all square cross
- section, and then all those with square sides. Finally the program
- should print out the complete inventory exactly as shown in Table 4.1.
-
- 2. Write a program to print all permutations of the facts (John), (Henry), and
- (Smith). That is the program should print all the possible combinations
- of the three facts, such as
-
- John Henry Smith
- John Smith Henry
- Henry John Smith
-
- and so forth.
-
-
-