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

  1.                 Chapter 7   Let's Be Logical
  2.  
  3.  
  4.  
  5.  
  6. In this chapter, you will learn how CLIPS deals with logical relations and 
  7. comparisons.  There are many useful applications of logical operations, 
  8.  especially when you write programs dealing with symbolic information.
  9.  
  10.  
  11. Three Into One Will Go
  12.  
  13.  
  14. So far all the rules you've seen have an implicit logical AND between the 
  15. conditional elements.  That is, a rule will not be triggered unless 
  16.  all of the conditional elements are true.  However, CLIPS also gives you the 
  17. capability of specifying explicitly logical AND conditions and 
  18.  also logical OR conditions on the LHS.
  19.    As an example of OR, let's first look at the following rules which are 
  20. written without an OR and then see how to rewrite them with an OR.
  21.  
  22. (defrule dont-walk
  23.    (light red)
  24. =>
  25.    (printout "Don't walk" crlf))
  26.  
  27. (defrule dont-walk
  28.    (walk-sign dont walk)
  29. =>
  30.    (printout "Don't walk" crlf))
  31.    
  32. (defrule dont-walk
  33.    (police say dont walk)
  34. =>
  35.    (printout "Don't walk" crlf))
  36.  
  37.    Rather than writing three separate rules, they can all be combined into the 
  38. following OR rule.
  39.  
  40. (defrule dont-walk
  41.    (or 
  42.       (light red)
  43.       (walk-sign dont walk)
  44.       (police say dont walk))
  45. =>
  46.    (printout "Don't walk" crlf))
  47.  
  48.    The group of conditional elements enclosed within the OR element is called a 
  49. logic block.  The one OR rule is equivalent to the three rules 
  50.  above.  Enter the OR rule and assert the three facts.  If you check the 
  51. agenda, you'll see that the rule is triggered three times with each 
  52.  of the facts.
  53.    Other conditional elements can be included outside the OR conditional and 
  54. will be part of the implicit AND.  For example, if the OR rule was
  55.  
  56. (defrule dont-walk
  57.    (status walking)
  58.    (or 
  59.       (light red)
  60.       (walk-sign dont walk)
  61.       (police say dont walk))
  62. =>
  63.    (printout "Don't walk" crlf))
  64.  
  65. the result would be equivalent to the three rules following.
  66.  
  67. (defrule dont-walk1
  68.    (status walking)
  69.    (light red)
  70. =>
  71.    (printout "Don't walk" crlf))
  72.  
  73. (defrule dont-walk2
  74.    (status walking)
  75.    (walk-sign dont walk)
  76. =>
  77.    (printout "Don't walk" crlf))
  78.  
  79. (defrule dont-walk3
  80.    (status walking)
  81.    (police say dont walk)
  82. =>
  83.    (printout "Don't walk" crlf))
  84.  
  85.    As you can see, the OR is similar to a true logical OR.  In a true logical 
  86. OR, the rule dont-walk would only be triggered once if one or more 
  87.  conditions are true.  However, in the OR of CLIPS, the dont-walk rule will be 
  88. triggered for each OR conditional element that is true, since 
  89.  the one OR rule is equivalent to three rules.  However, an OR rule does 
  90. function like a true logical OR in the sense that if any conditional 
  91.  element matches a fact, then the rule will be triggered.
  92.    Since multiple triggerings of an OR will occur with multiple facts, a 
  93. natural question is how to prevent the problem of more than one triggering. 
  94.   For example, we don't want multiple printouts of "Don't walk" appearing for 
  95. multiple facts.  After all, the robot only deals with one traffic 
  96.  light at a time.  Just because multiple facts may be true about the traffic 
  97. light doesn't mean we want a printout of "Don't walk" for each fact.
  98.    One possible solution to multiple triggerings you might think of is to 
  99. retract all the triggering facts when the rule fires once.  If all 
  100.  of the other triggering facts of the OR are retracted, the rule won't be 
  101. triggered again.  For example,
  102. (defrule dont-walk
  103.                (or 
  104.                   ?fact <- (light red)
  105.                   ?fact <- (walk-sign dont walk)
  106.                   ?fact <- (police say dont walk))
  107.             =>
  108.                (retract ?fact)
  109.                (printout "Don't walk" crlf))
  110.  
  111.    Notice that all conditional elements are bound to the same variable, ?fact.  
  112. At first, you may think this an error since you'd never assign 
  113.  the same variable to conditional elements of an ordinary rule.  But an OR rule 
  114. is different.  Since an OR is equivalent to multiple rules, the 
  115.  above rule is equivalent to the following three rules.
  116.  
  117. (defrule dont-walk1
  118.    (status walking)
  119.    ?fact <- (light red)
  120. =>
  121.    (retract ?fact)
  122.    (printout "Don't walk" crlf))    
  123.  
  124. (defrule dont-walk2
  125.    (status walking)
  126.    ?fact <- (walk-sign dont walk)
  127. =>
  128.    (retract ?fact)
  129.    (printout "Don't walk" crlf))
  130.  
  131. (defrule dont-walk3
  132.    (status walking)
  133.    ?fact <- (police say dont walk)
  134. =>
  135.    (retract ?fact)
  136.    (printout "Don't walk" crlf))
  137.  
  138.    By looking at the three rules, you can see that the same variable name was 
  139. necessary to match the (retract ?fact) action.  For example, suppose 
  140.  you had assigned separate names to the conditional elements such as ?light, 
  141. ?walk, and ?police and then used a (retract ?light ?walk ?police).
  142.  
  143. (defrule dont-walk
  144.    (status walking)
  145.    (or 
  146.       ?light <- (light red)
  147.       ?walk <- (walk-sign dont walk)
  148.       ?police <- (police say dont walk))
  149. =>
  150.    (retract ?light ?walk ?police)
  151.    (printout "Don't walk" crlf))
  152.  
  153.    The (retract ?light ?walk ?police) would be in error because two out of 
  154. three variables would not be defined in the equivalent rules.
  155.    Even though our rule does retract multiple facts, it still prints out 
  156. multiple "Don't walk" messages because the one rule is exactly the same 
  157.  as three rules.  Try it and see.
  158.    The correct solution to prevent multiple messages is to define a control 
  159. fact.  Consider the following program.
  160.  
  161. (defrule dont-walk
  162.    ?control <- (control-fact)
  163.    (status walking)
  164.    (or 
  165.       ?fact <- (light red)
  166.       ?fact <- (walk-sign dont walk)
  167.       ?fact <- (police say dont walk))
  168. =>
  169.    (retract ?control ?fact)
  170.    (printout "Don't walk" crlf))
  171.  
  172.    If the control fact is retracted, the rule cannot fire again.  It's as if 
  173. you retracted the (status walking) fact.  Strictly speaking, we 
  174.  don't even need to retract the ?fact.  However, it's a good idea to retract 
  175. all facts that characterize the current light situation so that 
  176.  the facts don't hang around and accidentally cause a firing if the control 
  177. fact is re-asserted.
  178. That is, what if the robot wanders on and encounters another light.  You don't 
  179. want the old light's facts in memory.
  180.  
  181.  
  182. And What's More
  183.  
  184.  
  185. The logical AND is opposite in concept to the logical OR.  Instead of any 
  186. conditional elements triggering a rule, the AND requires that all of 
  187.  the conditional elements be matched to facts.
  188.    Normally there is an implicit AND for the conditional elements of a rule.  A 
  189. rule such as
  190.  
  191. (defrule and-test
  192.    (status walking)
  193.    (walk-sign walk)
  194. =>
  195.    (printout "Walk" crlf))
  196.  
  197. could also be written with an explicit AND as
  198.  
  199. (defrule and-test
  200.       (and
  201.          (status walking)
  202.          (walk-sign walk))
  203. =>
  204.    (printout "Walk" crlf))
  205.  
  206. where the indentations are just to aid readability.
  207.    Of course, there is no advantage to writing a rule with an explicit AND.  
  208. It's more efficient to use the implicit AND of conditional elements 
  209.  if you don't need to specify an AND.
  210.    The AND is provided so that you can use it with the other logical functions 
  211. to make more powerful patterns.  For example, it can be used with 
  212.  an OR to require groups of multiple conditions be true, as shown in the 
  213. following example.
  214.  
  215. (defrule walk
  216.    (or (police says walk)
  217.        (and (walk-sign walk)
  218.             (light green))
  219.        (and (walk-sign walk)
  220.             (light yellow)))
  221. =>
  222.    (printout "Walk" crlf))
  223.  
  224.    Enter this rule and assert the facts
  225.  
  226. (police says walk)
  227. (walk-sign walk)
  228. (light green)
  229. (light yellow)
  230.  
  231. When you check facts, you'll see
  232.  
  233. f-0     (initial-fact)
  234. f-1     (police says walk)
  235. f-2     (walk-sign walk)
  236. f-3     (light green)
  237. f-4     (light yellow)
  238.  
  239.    Now check the agenda.  The rule will be triggered with the facts as shown 
  240. following.
  241.  
  242. 0   walk  f-2  f-4
  243. 0   walk  f-2  f-3
  244. 0   walk  f-1
  245.  
  246.    So the one rule called walk is equivalent to the three following rules, 
  247. where the comments identify the triggering facts.
  248.  
  249. (defrule walk
  250.    (walk-sign walk)       ; f-2 and f-4
  251.    (light yellow)
  252. =>
  253.    (printout "Walk" crlf))
  254.  
  255. (defrule walk
  256.    (walk-sign walk)       ; f-2 and f-3
  257.    (light green))
  258. =>
  259.    (printout "Walk" crlf))
  260.  
  261. (defrule walk
  262.    (police says walk)     ; f-1
  263. =>
  264.    (printout "Walk" crlf))
  265.  
  266.  
  267. Not My Constraint
  268.  
  269.  
  270. The previous rule are simplified ones that don't cover all cases such as the 
  271. breakdown of the traffic-light.  For example, what does the robot 
  272.  do if the light is red or yellow and the walk-sign says walk?
  273.    One way of handling this case is to use a field constraint to restrict the 
  274. values a pattern may have on the LHS.  The field constraints put 
  275.  limits on the values a pattern may have on the LHS.
  276.    There are two types of constraints.  The first type is called a logical 
  277. constraint.  There are three types of logical constraints.  The first 
  278.  type of logical constraint is called a negation constraint.  It's symbol is 
  279. the "~", called the tilde.  The negation is a prefix constraint 
  280.  acts on the one value that immediately follows it.
  281.    As a simple example of negation, suppose you wanted to write a very 
  282. conservative rule which would print out "Don't walk" if the light was 
  283.  not green.  This constraint is not the same as saying there is no fact (light 
  284. green) and so a (not) is not appropriate.     One approach would 
  285.  be to write rules for every possible light condition, such as yellow, red, 
  286. blinking yellow, binking red and so forth.   However, a much easier 
  287.  approach is to use the negation constraint, "~", as shown in the following 
  288. rule. 
  289.  
  290. (defrule walk
  291.    (light ~green)
  292. =>
  293.    (printout "Don't walk" crlf))
  294.  
  295. By using the negation constraint, this one rule does the work of many others 
  296. that required specifying each light condition.
  297.    Note that you cannot use the "!" and "!=" functions or any other RHS 
  298. functions on LHS patterns.  Likewise, the logical constraints cannot 
  299.  be used on the RHS.
  300.  
  301.  
  302. Be Cautious
  303.  
  304.  
  305. The second logical constraint is the OR constraint.  The OR constraint is 
  306. represented by the symbol "|", called the bar, and is an infix constraint. 
  307.   The OR constraint is used to allow any value in a pattern to match. 
  308.    For example, suppose you wanted a rule which printed out "Be cautious" if 
  309. the light was yellow or blinking yellow.  Here's how it's done using 
  310.  the "|" constraint.
  311.  
  312. (defrule cautious
  313.    (light yellow|blinking-yellow)
  314. =>
  315.    (printout "Be cautious" crlf))
  316.  
  317.    Enter this rule and then assert (light yellow) and (light blinking-yellow).  
  318. Check the agenda and you'll see that the rule is on the agenda 
  319.  for each fact.  Also, notice that the field blinking-yellow is connected by a 
  320. dash.  Since the logical constraints operate on single fields, 
  321.  you can't have (light yellow|blinking yellow) because then the constraint 
  322. would only be on yellow and blinking.   
  323.  
  324.  
  325. YAA
  326.  
  327.  
  328. The third type of logical constraint is yet another and, the AND constraint.  
  329. Its symbol is the "&", called the ampersand, and is an infix constraint. 
  330.   The "&" constraint is normally used only with the other constraints since 
  331. otherwise it's not of much practical use.
  332.    To understand where it's useful, let's first look at an example in which the 
  333. "&" is not useful.
  334.  
  335. (defrule green-light 
  336.    (light green&red)
  337. =>
  338.    (printout "Go" crlf))
  339.  
  340.    This rule will never be triggered since there is no possible fact whose 
  341. light is both green and red.  The conditional element will not match 
  342.  on green, red, or even greenred.
  343.    Here's another example of where the "&" is useless.
  344.  
  345. (defrule green-light 
  346.    (light green&~red)
  347. =>
  348.    (printout "Go" crlf))
  349.  
  350.    The conditional element will match a light whose color is green and not red. 
  351.  In this case, the rule can be triggered by the fact (light green) 
  352.  since green is green and not red.  However, it's much more efficient to just 
  353. write the rule as
  354.  
  355. (defrule green-light 
  356.    (light green)
  357. =>
  358.    (printout "Go" crlf))
  359.  
  360. since a light that is green cannot be red anyway.
  361.    Now let's see an example in which the "&" is useful. Suppose you want to 
  362. have a rule which will be triggered by a fact which is yellow or 
  363.  blinking yellow.  That's easy enough.  Just use the OR constraint, as you saw 
  364. in a previous example.
  365.  
  366. (defrule cautious
  367.    (light yellow|blinking-yellow)
  368. =>
  369.    (printout "Be cautious" crlf))
  370.  
  371. Suppose also that you want to identify the light color.
  372.    The solution is to bind a variable to the color that is matched using the 
  373. "&" and then print out the variable.  This is where the "&" is useful, 
  374.  as shown below.
  375.  
  376. (defrule cautious
  377.    (light ?color&yellow|blinking-yellow)
  378. =>
  379.    (printout "Be cautious" crlf))
  380.  
  381. The variable ?color will be bound to whatever color is matched by the field 
  382. yellow|blinking-yellow.
  383.    The reason for not using a (bind) is because it is a RHS function and so 
  384. cannot be used on the LHS.  Likewise, you cannot use the logical 
  385.  constraints on the RHS.
  386. .PA
  387.                             Problem
  388.  
  389.  
  390.    Write a program to simulate getting a car to run using the following 
  391. information.  The car has the following major components.
  392.  
  393. engine
  394. spark plugs
  395. battery
  396. gas tank
  397. wheels
  398.  
  399. For the car to move requires
  400.  
  401. gas in the gas tank
  402. oil in the engine
  403. coolant in the engine
  404. electricity in the spark plugs
  405. inflated tires on the wheels
  406.  
  407. If the gas, oil, coolant, and tires are not present, you must walk to a service 
  408. station and buy them.
  409.  
  410. If there is no electricity in the spark plugs, you must check the battery.
  411.  
  412. If the battery is good, you must call a service station to tow the car to the 
  413. service station.
  414.  
  415. If a tire is not inflated, you must check to see if there is a leak.
  416.  
  417. All four tires must be checked to see if they are inflated before the car can 
  418. operate.
  419.  
  420. If a tire has a leak, you must check the trunk to see if there is a jack and a 
  421. spare tire.
  422.  
  423. If there is no jack but there is a spare tire, you can borrow a jack from your 
  424. neighbor.
  425.  
  426. If there is a jack but no spare tire, you will borrow a tire from your spouse's 
  427. car, then drive to a service station and buy a spare.
  428.  
  429. If your car has been towed to a service station and you do not have towing 
  430. insurance, you must pay $49 from cash, check, or charge sources.
  431.  
  432.    If you are at the service station and do not have a single source of payment 
  433. to meet the cost of an item or towing, you must pay by combining 
  434.  sources.
  435.  
  436. For expert advice on how to pay, write a advice rule which will let you pay by 
  437. combining sources from cash, check, and charge.  The following 
  438.  facts should be considered by the rule and then it should tell you what to do. 
  439.  Do not encode the numbers in the following facts in the rule. 
  440.   The rule should bind data from the facts to appropriate variables in the rule.
  441.    You must always pay the towing charge in full and should buy as much gas and 
  442. oil as you can pay for.  You must have 1 container of coolant 
  443.  and at least 1 gallon of gas and 1 quart of oil for the car to run.  You 
  444. should try to buy as much as you can without overfilling.
  445.  
  446.                               Facts
  447.  
  448.       You do not have towing insurance.
  449.  
  450.       The service station will not accept checks over $49
  451.  
  452.       You have $20 in cash
  453.  
  454.       You do not have a credit card
  455.  
  456.       You have $80 in your checking account
  457.  
  458.       The towing charge is $50
  459.  
  460.       Gas is $1.09 a gallon
  461.  
  462.       Oil is 1.56 a quart
  463.  
  464.       Capacity of gas tank is 15 gallons
  465.  
  466.       Capacity of engine for oil is 5 quarts
  467.  
  468.       A new battery is $42.95
  469.  
  470.       A new tire is $69.96
  471.  
  472.       A container of coolant is $2.98
  473.  
  474.       There is 0.5 gallons of gas
  475.  
  476.       There is no oil
  477.  
  478.       Two of your tires have leaks
  479.  
  480.       You have a spare tire and no jack
  481.  
  482.       You need 1 container of coolant
  483.  
  484.       The battery is bad
  485.  
  486.       You must not overfill the gas tank, engine oil, or coolant
  487.  
  488.    Make a (deffacts) of the appropriate facts and run.  The program should tell 
  489. you what to check and what to do for all the problems that occur. 
  490.   Depending on what you input when you're asked to check something, the program 
  491. will take appropriate action.
  492.  
  493.  
  494.