home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / compiler / clips / clip_doc / clips8.man < prev    next >
Encoding:
Text File  |  1993-09-01  |  14.5 KB  |  376 lines

  1.              Chapter 8   Powerful Patterns
  2.  
  3.  
  4.  
  5.  
  6. In this chapter, you will learn more of the powerful pattern matching 
  7. capabilities of CLIPS.  By effectively using this capability you can greatly 
  8.  reduce the number of rules required by programs and also make them more easily 
  9. understandable.
  10.  
  11. Stronger Than Logic
  12.  
  13.  
  14. In the previous chapter, you learned about one type of field constraint, the 
  15. logical constraint which uses "&", "|", or "~".  The second type 
  16.  of field constraint is called a predicate function, and is commonly used for 
  17. more complex pattern matching of a field.  You'll find the predicate 
  18.  function very useful with numeric patterns.
  19.    A predicate function uses a special form of the "&" constraint called the 
  20. AND function and symbolized by "&:".  The general form is 
  21.  
  22. ?variable&:(<fun> <<arg>>)
  23.  
  24. where 
  25.    ?variable is any legal variable name
  26.    <fun> is a predefined or user defined function
  27.    <<arg>> are zero or more arguments required by the function
  28.  
  29.    Any predefined or user defined function can be used as a function.  The 
  30. predefined functions are those shown in the section on the test function 
  31.  in the section "Control Your Loop" of Chapter 6, and also in Appendix A of the 
  32. Reference Manual.  The math functions can also be used if you 
  33.  have a version of CLIPS which has been linked to the math library.
  34.    The "&:" function operates by initially binding the value in the field to 
  35. ?variable and then performing the test (<fun> <<arg>>).  If the 
  36.  test is succesful, the conditional element is true.
  37.    As a very simple example, consider the following.
  38.  
  39. (defrule compare
  40.    (?x&:(> 2 1))
  41.    =>
  42.    (printout "answer " ?x crlf))
  43.  
  44.    Enter and assert a 1.  When you run, the same fact will be printed.  In 
  45. fact, the rule will always print out whatever facts are asserted because 
  46.  the predicate function test is always true.  That is, since 2 > 1 is always 
  47. true, any fact meets the criteria of the predicate function and 
  48.  will be bound to ?x.
  49.    A more useful form of the predicate function will use the variable as one of 
  50. the arguments.  For example, suppose you wanted to test which 
  51.  numbers are greater than 1.  The modified rule would now be
  52.  
  53. (defrule compare
  54.    (?x&:(> ?x 1))
  55.    =>
  56.    (printout "answer " ?x crlf))
  57.  
  58.    Before you enter this rule, do not have an (initial-facts) or other 
  59. non-number in the fact-list.  The reason is that CLIPS will try to match 
  60.  the conditional element on (initial-fact).  So give an error message because 
  61. (initial-fact) is not a number and the test (> ?x 1) is invalid. 
  62.   If there is a non-numeric fact such as (initial-fact), you'll see an error 
  63. message 
  64.  
  65. Non-float argument #1 found in function > in rfloat call
  66.  
  67. With no non-numeric fact present, enter the rule and assert the numbers 0, 1, 
  68. 2, 3, and 4.  When you run, you'll see that the numbers greater 
  69.  than 1 are indeed printed out.
  70.    In order to prevent error messages like the above, you can either try never 
  71. to have a non-numeric fact or tighten up the constraints on the 
  72.  facts to be matched.  For example, the rule could be changed to 
  73.  
  74. (defrule compare
  75.    (number ?x&:(> ?x 1))
  76.    =>
  77.    (printout "answer " ?x crlf))
  78.  
  79. and then you would assert facts like (number 0), (number 1), and so forth.  Now 
  80. (initial-fact) cannot match the conditional element and the error 
  81.  message does not occur.
  82.    Notice that the "&:" constraint now applies to the second field in the 
  83. conditional element.  Using constraints, wildcards, and tests gives 
  84.  you a very powerful pattern matching capability.
  85.    The presence of the extra "number" pattern in the first field means that 
  86. CLIPS must do a little more matching to trigger a rule.  However, 
  87.  the extra matching time is insignificant.  The important thing is that extra 
  88. fields aid in debugging a program because they explicitly show 
  89.  what the facts are supposed to be.
  90.    You may be wondering why the second version of the program involving ?x 
  91. produced the error message and the first with (> 2 1) did not.  The 
  92.  reason is that CLIPS did not have to test ?x in (> 2 1) and so did not find an 
  93. error in comparing initial-fact to 1.
  94.    Now suppose you want those numbers which are greater than 1 and less than 4. 
  95.  No sweat.  Just add the following conditional element to check 
  96.  if ?x is < 4.
  97.  
  98. (defrule compare
  99.    (number ?x&:(> ?x 1))
  100.    (number ?x&:(< ?x 4))   ; add this conditional element
  101.    =>
  102.    (printout "answer " ?x crlf))
  103.  
  104.    After you change the rule, check the agenda.  Notice that the facts for the 
  105. numbers 2 and 3 are listed twice since they match the two conditional 
  106.  elements of the rule.  If nothing is on the agenda, you probably didn't assert 
  107. the facts with a "number" in the first field.  When you run, 
  108.  the rule will print out the correct numbers 2 and 3.
  109.    Is there any way to write the rule using only one conditional element? There 
  110. is, as shown by the following rule.
  111.  
  112. (defrule compare
  113.    (number ?x&:(&& (> ?x 1)) (< ?x 4))
  114.    =>
  115.    (printout "answer " ?x crlf))
  116.  
  117. The one conditional element says that ?x must be greater than 1 and less than 
  118. 4.  Notice that the logical AND, "&&", must be used as the connector 
  119.  for the two comparisons (> ?x 1) and (< ?x 4).
  120.  
  121.  
  122. The Truth Of The Matter
  123.  
  124.  
  125. A function that returns a value of 0 is considered false, while non-zero is 
  126. true.  As an simple example, consider the following.
  127.  
  128. (defrule and-1
  129.    (number ?x&:1)
  130.    =>
  131.    (printout "true" crlf))
  132.  
  133. (defrule and-0
  134.    (number ?x&:0)
  135.    =>
  136.    (printout "false" crlf))
  137.  
  138.    Notice that there is a number after the "&:" rather than a function and 
  139. arguments in parentheses.  The number alone indicates the value that 
  140.  would have been returned by a function.  An alternative is a function that is 
  141. always true like (= 1 1) or one that is always false like (= 1 
  142.  0).
  143.    Enter these rules and then do a (reset).  As expected, the and-1 is on the 
  144. agenda while the and-0 is not.  If you replace the 1 and 0 after 
  145.  the "&:" with the always true and always false function, you'll see the same 
  146. results.
  147.    How would you invert the logic of the function result to make a false become 
  148. true?  The answer is shown in the following modification of the 
  149.  and-0 rule.  The logical not, "!", is used to invert the 0.  Enter this rule 
  150. and (reset).  You'll see that it is on the agenda.
  151.  
  152. (defrule and-0-true
  153.    (number ?x&:(! 0))
  154.    =>
  155.    (printout "false" crlf))
  156.  
  157.    The same considerations of true and false apply to test conditions.  For 
  158. example, enter the following, (reset), and check the agenda.
  159.  
  160. (defrule test-1
  161.    (number ?x)
  162.    (test 1)
  163.    =>
  164.    (printout "true" crlf))
  165.  
  166. (defrule test-0
  167.    (number ?x)
  168.    (test 0)
  169.    =>
  170.    (printout "false" crlf))
  171.  
  172.    Normally you'd never intentionally use constant functions like this since 
  173. they are not of practical use.  However, you might accidentally 
  174.  write one involving variables such as
  175.  
  176. (defrule error
  177.    (number ?x&:(> ?x ?x))
  178. =>
  179.    (printout "false" crlf))
  180.  
  181. The programmer probably meant to write a conditional element like (number 
  182. ?x&:(> ?x ?y)) but accidentally typed a ?x.  Since a number cannot 
  183.  be greater than itself, the function is always false and the rule is never 
  184. triggered.
  185.    If you write your own functions, they must return 0 for false and a nonzero 
  186. value for true.  Any nonzero number will do.
  187.  
  188.  
  189. You Just Can't Get Enough
  190.  
  191.  
  192. Besides the predefined functions, there are some other predicate functions that 
  193. are very useful, especially with "&:".  These predicate functions 
  194.  are used to test strings and numbers.  As the old saying goes, you just can't 
  195. get enough of a good thing.  Notice that there is a "p" after 
  196.  each function.  The reason for the "p" is that these functions were originally 
  197. defined in LISP and that's how LISP defines them.
  198.  
  199.    Function               Purpose
  200.  
  201. (numberp <arg>)      Check if <arg> is a number
  202. (stringp <arg>)      Check if <arg> is a string
  203. (evenp <arg>)        Check if <arg> is even
  204. (oddp <arg>)         Check if <arg> is odd
  205.        
  206.    As an example, consider the following rules to print out the odd and even 
  207. numbers in the fact-list.  Note that there may also be non-numbers, 
  208.  but only the numbers will be printed out.
  209.  
  210. (defrule odd-number
  211.    (?x&:(&& (numberp ?x) (oddp ?x)))
  212. =>
  213.    (printout ?x " is an odd number" crlf))
  214.  
  215. (defrule even-number
  216.    (?x&:(&& (numberp ?x) (evenp ?x)))
  217.    =>
  218.    (printout ?x " is an even number" crlf))
  219.  
  220. The "number" field is not necessary now because the "numberp" checks to see if 
  221. the fact is a number.
  222.    Enter and assert the facts duck, cat, -2, -1, 0, 1, and 2.  Check the agenda 
  223. and you'll see that the rules do match the correct numbers.
  224.  
  225.  
  226. Pushing CLIPS
  227.  
  228.  
  229. Let's take a look at another example.  This one will really push CLIPS by 
  230. straining its pattern matching and arithmetic capability.
  231.    Suppose you want a program that will determine if three numbers are perfect 
  232. squares.  That is, what integer numbers x, y, and z will satisfy 
  233.  the equality
  234.  
  235. z * z = x * x + y * y
  236.  
  237.   First of all, we'll have to agree on some limits to the problem.  Since there 
  238. are infinitely many numbers that satisfy the equality, we'll 
  239.  let the user pick a certain range of numbers for CLIPS to test.
  240.    The program will be written as three rules.  The input-limits rule will let 
  241. the user specify the initial and final values of numbers.  The 
  242.  make-numbers rule will then assert the integers from initial to final value. 
  243. The perfect-squares rule will then find the perfect squares from 
  244.  the numbers asserted by the make-numbers rule.  Shown following are the first 
  245. two rules of the program.
  246.  
  247. (defrule input-limits
  248.    (initial-fact)
  249. =>
  250.    (printout "Initial number ? " crlf)
  251.    (bind ?initial (read))
  252.    (printout "Final number ? " crlf)
  253.    (assert (limits =(read) ?initial))) ;final and initial limits
  254.  
  255. (defrule make-numbers
  256.    (declare (salience 10))
  257.    ?limits <- (limits ?final ?initial&:(<= ?initial ?final))
  258. =>
  259.    (retract ?limits)
  260.    (printout "number " ?initial " asserted" crlf)
  261.    (assert (number ?initial))
  262.    (bind ?initial (+ ?initial 1))
  263.    (assert (limits ?final ?initial)))
  264.  
  265.    Enter these two rules and run for an initial limit of 1 and a final limit of 
  266. 7.  Notice how quickly CLIPS prints the asserted numbers.  Now 
  267.  enter a (reset) command.  Then enter the third rule to find numbers which are 
  268. perfect squares.
  269.  
  270. (defrule perfect-squares
  271.    (number ?x)
  272.    (number ?y)
  273.    (number ?z&:(= (* ?z ?z) (+ (* ?x ?x) (* ?y ?y))))
  274.             =>
  275.    (printout "x = " ?x " y = " ?y " z = " ?z crlf))
  276.  
  277.    The salience conditional element in the make-numbers rule is to insure that 
  278. all the asserted numbers are asserted before the perfect-squares 
  279.  rule is triggered.  Now run the program for the same limits as before of 1 and 
  280. 7.
  281.    The third conditional element in perfect squares is the equality to be 
  282. tested.  It checks if the sum of the square of z is the sum of the 
  283.  squares of x and y.   Enter and run the program as before for initial and 
  284. final numbers of 1 and 7.  Notice that it takes CLIPS longer and longer 
  285.  to assert the numbers now that the perfect-squares rule is present.
  286.    The reason for the delays in asserting numbers is that CLIPS also checks 
  287. which rules are triggered every time a new fact is asserted.  Since 
  288.  there are more facts, there are more comparisons to check.  Try to calculate 
  289. how many checks of facts against conditional elements there are 
  290.  as each new fact is added.
  291.    As soon as a fact is asserted, CLIPS starts checking for matches against 
  292. rules.  In other languages such as FORTAN, Pascal, Ada, and C, nothing 
  293.  happens until you issue a run command.  But in CLIPS and LISP, the interpreter 
  294. is always running.  The situation is analogous to BASIC in which 
  295.  the interpreter is always running and will immediately execute a command 
  296. without a line number.  In CLIPS, the interpreter automatically matches 
  297.  rules against facts, even before your program starts executing.
  298.    Now you can see why you were asked to enter and run the first two rules 
  299. before the third rule.  This way, you have gained a better understanding 
  300.  of how CLIPS operates than if you had just typed in all three rules at once.
  301.    A more efficient method of writing the program is to eliminate the salience 
  302. conditional element in the make-numbers rule.  The salience was 
  303.  included to just illustrate the difference in execution speed before and after 
  304. the perfect-squares rule was added.  Try running the program 
  305.  without salience also.   
  306. .PA
  307.                              Problems
  308.  
  309.  
  310. 1.  Write a program that will first assert the numbers from 1 to 24 and then 
  311. determine which are factorials.
  312.  
  313.  
  314. 2.  Write a program to give directions to a robot on how to go from point 1 to 
  315. point 2 by the shortest path.  The directions will tell how to 
  316.  move one square at a time in the form
  317.  
  318. move north
  319. move south
  320. move east
  321. move west
  322.  
  323. Different traffic lights and buildings will be asserted from a (deffacts), 
  324. whose facts are in the form
  325.  
  326. (building x y)
  327.  
  328. (light red x y)
  329.  
  330. (light green x y)
  331.  
  332. and so forth for the other light conditions.  The x and y coordinates are shown 
  333. followed by a diagram.  Use the x and y coordinates for the buildings 
  334.  and lights shown.  The robot starts at x = 0, y = 0.  The goal is at x = 9, y 
  335. = 9.  Ideally, the robot will travel in a straight line to the 
  336.  goal.
  337.    For each move, print out the direction to travel and update the diagram.  
  338. The symbols on the diagram represent the following.
  339.  
  340. B   building
  341. O   robot
  342. X   goal
  343. r   red light
  344. y   yellow light
  345. g   green
  346. G   blinking green - The light is broke.  Cannot go in this square
  347. Y   blinking yellow
  348. R   blinking red 
  349.  
  350.    The robot must be in a square to know what is in the immediately surrounding 
  351. squares.  That is, the robot can only look at the immediately 
  352.  adjacent eight squares.  It cannot go past the borders, into a building, or 
  353. into a broken light.
  354.    Hint: If you can't go in a straight line, then always go in one consistent 
  355. direction, such as right or left.
  356.  
  357.  
  358.  
  359.                           ------------                            
  360.                          9|      BB X|
  361.                          8|   GB  r  |
  362.           N              7|   BBBB   |
  363.         W   E            6|  R  YBB  |
  364.           S           Y  5|  g BrBBB |
  365.                          4|  B  y  B |
  366.                          3|BBB  B   B|
  367.                          2|  BBBg BBB|
  368.                          1|   Br B   |
  369.                          0|O         |
  370.                           ------------
  371.                            0123456789
  372.  
  373.                                X
  374.  
  375.  
  376.