; Author: David Osbourn ; Student Number: 0232786 ; Date: 17/03/2004 ; ; Description: Rules for Cars Expert system for Autonomic Computing coursework ; Answer to the final 5 mark question, ; How do you identify which order these rules should be applied in? ; ; I applied the rules (asked the questions) in the order I did as I felt asking the broadest ; question first stood to eliminate the largest number and immediately remove those cars ; that didn't match the users initial stipulation. The next question is regarding the price ; of the car, if the user doesn't know or the price isn't important to them then JESS ; jumps straight to asking about the engine size. If the price is important then the user ; is asked what their price range is. In actual fact, if the user answers 2 or 3 for the price ; question then the upper limit of their price range is set to 500000 (as no car in the list ; costs that much) and the lower limit of the price range is set to 0, hence not eliminating ; any cars. The remainder of the rules are in a fairly arbitrary order. (reset) ; Start a-fresh (clear) ; Just to be sure (deftemplate car ; The template that holds all the car data (slot manufacturer) (slot model) (slot cc (type integer)) ; engine size (slot colour) (slot price (type float)) (slot acceleration (type float)) ; 0 - 60 time (slot consumption (type float)) ; mpg (slot reliability (type integer)) ; 1 = bad, 5 = good (slot coManuf) ; Country of Manufacture ) (deftemplate treepath ; A list of nodes and their 'next' nodes. (slot current) (slot next) ) (defrule initialize-1 ; Load all the data from the files. (declare (salience 3000)) (not (car (manufacturer ?manuf))) (not (init)) (not (node ?a)) => (printout t "Initialising..." crlf) (batch car-defs.clp) ; Read in the car data (batch tree-order.clp) ; Read in the order in which to process the nodes (assert (init)) ) ; Rule set follows.... ; Rules run from A through to V (22 in total) (defrule rReliable1 "A - BMWs are reliable" (declare (salience 2022)) (init) (car (manufacturer BMW) (model ?model)) => (assert (reliable BMW ?model)) ) (defrule rReliable2 "B - Japanese and Korean cars are reliable" (declare (salience 2021)) (init) (car (manufacturer ?manufacturer) (model ?model) (coManuf ?country& Japan | Korea)) => (assert (reliable ?manufacturer ?model)) ) (defrule rReliable3 "C - Cars with reliability >= 3 are reliable" (declare (salience 2020)) (init) (car (manufacturer ?manufacturer) (model ?model) (reliability ?rel)) (test (>= ?rel 3)) => (assert (reliable ?manufacturer ?model)) ) (defrule rCheaper1 "D - UK Cars are cheaper in the UK" (declare (salience 2019)) (init) (car (manufacturer ?manufacturer) (model ?model) (coManuf UK)) => (assert (cheaper UK ?manufacturer ?model)) ) (defrule rCheaper2 "E - US Cars are cheaper in the US" (declare (salience 2018)) (init) (car (manufacturer ?manufacturer) (model ?model) (coManuf US)) => (assert (cheaper US ?manufacturer ?model)) ) (defrule rAppeal1 "F - Red || Black => Appeal" (declare (salience 2017)) (init) (car (manufacturer ?manufacturer) (model ?model) (colour ?colour& Red | Black)) => (assert (appeal ?manufacturer ?model)) ) (defrule rAppeal2 "G - Italian => Appeal" (declare (salience 2016)) (init) (car (manufacturer ?manufacturer) (model ?model) (coManuf Italy)) => (assert (appeal ?manufacturer ?model)) ) (defrule rLessAccidents "H - Yellow => Less Accidents" (declare (salience 2015)) (init) (car (manufacturer ?manufacturer) (model ?model) (colour Yellow)) => (assert (lessAccidents ?manufacturer ?model)) ) (defrule rSafety "I - Swedish && German => Safety" (declare (salience 2014)) (init) (car (manufacturer ?manufacturer) (model ?model) (coManuf ?country& Sweden | Germany)) => (assert (safety ?manufacturer ?model)) ) (defrule rFast "J - Acceleration < 7 => Fast" (declare (salience 2013)) (init) (car (manufacturer ?manufacturer) (model ?model) (acceleration ?acc)) (test (< ?acc 7.0)) => (assert (fast ?manufacturer ?model)) ) (defrule rExpensive "K - Price > 20k => expensive" (declare (salience 2012)) (init) (car (manufacturer ?manufacturer) (model ?model) (price ?price)) (test (> ?price 18000)) => (assert (expensive ?manufacturer ?model)) ) (defrule rModerate "K' - Price > 10k => moderate" (declare (salience 2011)) (init) (car (manufacturer ?manufacturer) (model ?model) (price ?price)) (test (> ?price 9999)) (test (< ?price 18001)) => (assert (moderate ?manufacturer ?model)) ) (defrule rCheap "L - Price < 10000 => cheap" (declare (salience 2010)) (init) (car (manufacturer ?manufacturer) (model ?model) (price ?price)) (test (< ?price 10000)) => (assert (cheap ?manufacturer ?model)) ) (defrule rEngineLarge "M - cc > 2500 => engine Large" (declare (salience 2009)) (init) (car (manufacturer ?manufacturer) (model ?model) (cc ?cc)) (test (> ?cc 2500)) => (assert (engine Large ?manufacturer ?model)) ) (defrule rEngineSmall "N - cc < 1300 => engine Small" (declare (salience 2008)) (init) (car (manufacturer ?manufacturer) (model ?model) (cc ?cc)) (test (< ?cc 1300)) => (assert (engine Small ?manufacturer ?model)) ) (defrule rLowFuelEc "O - US || M => lowFuelEc" (declare (salience 2007)) (init) (or (engine Large ?manufacturer ?model) (car (manufacturer ?manufacturer) (model ?model) (coManuf US)) ) => (assert (lowFuelEc ?manufacturer ?model)) ) (defrule rHighFuelEc "P - consumption > 33 => highFuelEc" (declare (salience 2006)) (init) (car (manufacturer ?manufacturer) (model ?model) (consumption ?consump)) (test (> ?consump 30)) => (assert (highFuelEc ?manufacturer ?model)) ) (defrule rSportsHighInsurance "Q - (F || G) && (M || J) == F && (M || J) => sportsCar && insurance High Both F and G are the same as they both assert appeal, so no need for F || G" (declare (salience 2005)) ; Longhand version, but the LHS is implicitly enclosed in an and conditional element. ; I can not work out the shorthand version ;) (init) (and (appeal ?manufacturer ?model) (or (and (engine Large ?manufacturer1 ?model1) (and (test (eq ?manufacturer ?manufacturer1)) (test (eq ?model ?model1)) ) ) (and (fast ?manufacturer2 ?model2) (and (test (eq ?manufacturer ?manufacturer2)) (test (eq ?model ?model2)) ) ) ) ) => (assert (sportsCar ?manufacturer ?model)) (assert (insurance High ?manufacturer ?model)) ) (defrule rExpensive2Run "R - (O || Q) && !H => expensive2run" (declare (salience 2004)) (init) ;Longhand version, but the LHS is implicitly enclosed in an and conditional element. ; (and (lessAccidents ?manufacturer1 ?model1) ; (and (or (lowFuelEc ?manufacturer ?model) ; (insurance High ?manufacturer ?model) ; ) ; (and (test (neq ?manufacturer ?manufacturer1)) ; (test (neq ?model ?model1)) ; ) ; ) ; ) ; Shorthand Version (lessAccidents ?manufacturer1 ?model1) (or (lowFuelEc ?manufacturer ?model) (insurance High ?manufacturer ?model) ) (test (neq ?manufacturer ?manufacturer1)) (test (neq ?model ?model1)) => (assert (expensive2run ?manufacturer ?model)) ) (defrule rQuality "S - (K' && reliability =5) || K && (A || B || C) => quality Since A, B and C all assert reliable ?manufacturer ?model there is no need to carry out the ORs" (declare (salience 2003)) (init) (or (and (expensive ?manufacturer ?model) (and (reliable ?manufacturer1 ?model1) (and (test (eq ?manufacturer ?manufacturer1)) (test (eq ?model ?model1)) ) ) ) (and (moderate ?manufacturer ?model) (and (car (manufacturer ?manufacturer1) (model ?model1) (reliability ?rel)) (and (test (>= ?rel 4)) (and (test (eq ?manufacturer ?manufacturer1)) (test (eq ?model ?model1)) ) ) ) ) (and (cheap ?manufacturer ?model) (and (car (manufacturer ?manufacturer1) (model ?model1) (reliability ?rel)) (and (test (= ?rel 5)) (and (test (eq ?manufacturer ?manufacturer1)) (test (eq ?model ?model1)) ) ) ) ) ) => (assert (quality ?manufacturer ?model)) ) (defrule rInsuranceCheap "T - N || L => insurance Cheap" (declare (salience 2002)) (init) (or (engine Small ?manufacturer ?model) (cheap ?manufacturer ?model)) => (assert (insurance Cheap ?manufacturer ?model)) ) (defrule rSuitableYounger "U - French && N => suitable Younger" (declare (salience 2001)) (init) (car (manufacturer ?manufacturer) (model ?model) (coManuf France)) (engine Small ?manufacturer1 ?model1) (test (eq ?manufacturer ?manufacturer1)) (test (eq ?model ?model1)) => (assert (suitable Younger ?manufacturer ?model)) ) (defrule rSuitableOlder "V - (A || B || C) && P && (S || I) => suitable Older Since A, B and C all assert reliability there is no need to do the OR" (declare (salience 2000)) (init) (reliable ?manufacturer ?model) (highFuelEc ?manufacturer1 ?model1) (or (quality ?manufacturer2 ?model2) (safety ?manufacturer2 ?model2)) (test (eq ?manufacturer ?manufacturer2)) (test (eq ?model ?model2)) (test (eq ?manufacturer ?manufacturer1)) (test (eq ?model ?model1)) => (assert (suitable Older ?manufacturer ?model)) ) ; Rules for Decision Tree (defrule nIntro ; Display the welcome message (declare (salience -101)) ?i <- (init) (treepath (current intro) (next ?next)) => (printout t crlf "MyAuto.com is designed to help you make the right decision about the kind of car " crlf "you should purchase. Let us help you decide." crlf) (assert (node ?next)) (retract ?i) ) (defrule nMainFactor (declare (salience 1)) (node mainfactor) => (printout t crlf "What is the main factor in making a purchase decision for you?" crlf " (1) price (low running costs)," crlf " (2) good fuel economy," crlf " (3) comfort," crlf " (4) performance," crlf " (5) safety," crlf " (6) reliability," crlf " (7) quality," crlf " (8) don't care." crlf " Answer [1-8]: ") (assert (answer (read))) (assert (node checkanswer)) ) (defrule nBadChoice ; Check selected is valid, otherwise ask again (declare (salience 0)) ?chk <- (node checkanswer) ?n <- (node mainfactor) ?ans <- (answer ?a) (or (test (< ?a 1)) (test (> ?a 8)) ) => (printout t crlf "*** Bad Answer, please reanswer question ***" crlf crlf) (retract ?ans ?chk ?n) (assert (node mainfactor)) ) (defrule nFactorAnswer1 ; Price - user enters main factor, remove the ones that don't match (declare (salience 1)) ?n <- (node mainfactor) (answer 1) ?c <- (car (manufacturer ?manuf)(model ?model)) (expensive2run ?manuf ?model) => ;(printout t "Removing " ?manuf ", " ?model crlf) (retract ?c) (assert (node factorcleanup)) ) (defrule nFactorAnswer2 ; Fuel Economy - user enters main factor, remove the ones that don't match (declare (salience 1)) ?n <- (node mainfactor) (answer 2) ?c <- (car (manufacturer ?manuf)(model ?model)) (not (highFuelEc ?manuf ?model)) => ;(printout t "Removing " ?manuf ", " ?model crlf) (retract ?c) (assert (node factorcleanup)) ) (defrule nFactorAnswer3 ; comfort/quality - user enters main factor, remove the ones that don't match (declare (salience 1)) ?n <- (node mainfactor) (or (answer 3) (answer 7) ) ?c <- (car (manufacturer ?manuf)(model ?model)) (not (quality ?manuf ?model)) => ;(printout t "Removing " ?manuf ", " ?model crlf) (retract ?c) (assert (node factorcleanup)) ) (defrule nFactorAnswer4 ; peformance - user enters main factor, remove the ones that don't match (declare (salience 1)) ; performance = fast or appeal ?n <- (node mainfactor) (answer 4) ?c <- (car (manufacturer ?manuf)(model ?model)) (not (fast ?manuf ?model)) (not (appeal ?manuf ?model)) => ;(printout t "Removing " ?manuf ", " ?model crlf) (retract ?c) (assert (node factorcleanup)) ) (defrule nFactorAnswer5 ; Safety - user enters main factor, remove the ones that don't match (declare (salience 1)) ?n <- (node mainfactor) (answer 5) ?c <- (car (manufacturer ?manuf)(model ?model)) (not (safety ?manuf ?model)) => ;(printout t "Removing " ?manuf ", " ?model crlf) (retract ?c) (assert (node factorcleanup)) ) (defrule nFactorAnswer6 ; Reliable - user enters main factor, remove the ones that don't match (declare (salience 1)) ?n <- (node mainfactor) (answer 6) ?c <- (car (manufacturer ?manuf)(model ?model)) (not (reliable ?manuf ?model)) => ;(printout t "Removing " ?manuf ", " ?model crlf) (retract ?c) (assert (node factorcleanup)) ) (defrule nFactorAnswer8 ; None - user enters main factor, remove the ones that don't match (declare (salience 1)) ?n <- (node mainfactor) (answer 8) => (assert (node factorcleanup)) ) (defrule nFactorCleanup ; Cleanup the assertions made during the price selection and matching. (declare (salience 0)) ?t <- (node factorcleanup) ?a <- (answer ?x) ?chk <- (node checkanswer) ?n <- (node mainfactor) (treepath (current mainfactor) (next ?next)) => (retract ?n ?a ?chk ?t) (assert (node ?next)) ; go to the next node ) (defrule nPrice ; Ask about the price (declare (salience 1)) (node price) => (printout t crlf "Is the price of the car:" crlf " (1) important," crlf " (2) unimportant," crlf " (3) don't know." crlf " Answer [1-3]: ") (assert (answer (read))) (assert (node checkanswer)) ) (defrule nBadPrice ; Check selected is valid, otherwise ask again (declare (salience 0)) ?chk <- (node checkanswer) ?n <- (node price) ?ans <- (answer ?a) (or (test (< ?a 1)) (test (> ?a 3)) ) => (printout t crlf "*** Bad Answer, please reanswer question ***" crlf crlf) (retract ?ans ?chk ?n) (assert (node price)) ) (defrule nPriceAnswer ; If user enters one them prompt for price range (declare (salience 1)) ?n <- (node price) (answer 1) => (printout t "What is your price range?" crlf) (printout t " Lower Limit: ") (assert (lower (read))) ; Read limits (printout t " Upper Limit: ") (assert (upper (read))) (retract ?n) (assert (node price2)) ) (defrule nPriceAnswer2 ; If the user enters 2 or 3, i.e. they don't care about the price set the price range to default, 0 to 500000 (declare (salience -1)) ?n <- (node price) (answer ?a) => (assert (lower 0)) (assert (upper 500000)) (retract ?n) (assert (node price2)) ) (defrule nPriceRejects-1 ; Remove those cars that fall outside the price range (declare (salience 1)) (node price2) (lower ?low) (upper ?up) ?c <- (car (manufacturer ?manuf) (model ?model) (price ?price)) (or (test (>= ?price ?up)) (test (< ?price ?low)) ) => (retract ?c) ;(printout t "Removing " ?model ", " ?price ", " ?up ", " ?low crlf) (assert (node pricecleanup)) ) (defrule nPriceRejects-2 ; Catch all for Price, ensures clean up is called and if no cars are rejected by matches above (declare (salience -1)) (node price2) => (assert (node pricecleanup)) ) (defrule nPriceCleanup ; Cleanup the assertions made during the price selection and matching. (declare (salience 0)) ?t <- (node pricecleanup) ?l <- (lower ?c) ?u <- (upper ?b) ?a <- (answer ?x) ?chk <- (node checkanswer) ?n <- (node price2) (treepath (current price) (next ?next)) => (retract ?l ?u ?n ?a ?chk ?t) (assert (node ?next)) ; go to the next node ) (defrule nEngine ; Ask about the engine size (node engine) => (printout t crlf "Engine size preference (cc in litres):" crlf " (1) cc < 1.5," crlf " (2) 1.5 <= cc < 2.0," crlf " (3) 2.0 <= cc < 2.8," crlf " (4) cc > 2.8," crlf " (5) don't know." crlf " Answer [1-5]: ") (assert (answer (read))) (assert (node checkanswer)) ) (defrule nBadEngine ; Is the answer from above out of the range? If so ask again (declare (salience 0)) ?chk <- (node checkanswer) ?n <- (node engine) ?ans <- (answer ?a) (or (test (< ?a 1)) (test (> ?a 5)) ) => (printout t crlf "*** Bad Answer, please reanswer question ***" crlf crlf) (retract ?ans ?chk ?n) (assert (node engine)) ) (defrule nEngineMatches1 ; Set limits for engine sizes, depending on user selection (declare (salience 1)) ?e <- (node engine) (answer 1) => (assert (cc_upper 1500)) (assert (cc_lower 0)) (assert (node engineset)) (retract ?e) ) (defrule nEngineMatches2 ; Set limits for engine sizes, depending on user selection (declare (salience 1)) ?e <- (node engine) (answer 2) => (assert (cc_upper 2000)) (assert (cc_lower 1499)) (assert (node engineset)) (retract ?e) ) (defrule nEngineMatches3 ; Set limits for engine sizes, depending on user selection (declare (salience 1)) ?e <- (node engine) (answer 3) => (assert (cc_upper 2800)) (assert (cc_lower 1999)) (assert (node engineset)) (retract ?e) ) (defrule nEngineMatches4 ; Set limits for engine sizes, depending on user selection (declare (salience 1)) ?e <- (node engine) (answer 4) => (assert (cc_upper 50000)) (assert (cc_lower 2799)) (assert (node engineset)) (retract ?e) ) (defrule nEngineMatches5 ; Set limits for engine sizes, depending on user selection (declare (salience 1)) ?e <- (node engine) (answer 5) => (assert (cc_upper 50000)) (assert (cc_lower 0)) (retract ?e) (assert (node enginecleanup)) ; Nothing to elliminate as user doesn't care about engine size, therefore jump straight to cleanup (assert (node engineset)) ; NOTE: we must set cc_upper & cc_lower or cleanup won't fire ) (defrule nEngineRejects-1 ; Test cars against limits set above, remove those that don't match (declare (salience 1)) (node engineset) (cc_upper ?up) (cc_lower ?low) ?c <- (car (manufacturer ?manuf) (model ?model) (cc ?cc)) (or (test (>= ?cc ?up)) (test (< ?cc ?low)) ) => (retract ?c) ;(printout t "Removing " ?model ", " ?cc ", " ?up ", " ?low crlf) (assert (node enginecleanup)) ) (defrule nEngineRejects-2 ; Catch all for engine rejects, in case none were eliminated above (declare (salience 0)) (node engineset) => (assert (node enginecleanup)) ) (defrule nEngineCleanup ; Clearing up assertions made during engine checks ?e <- (node enginecleanup) ?s <- (node engineset) ?a <- (answer ?x) ?l <- (cc_lower ?y) ?u <- (cc_upper ?z) ?chk <- (node checkanswer) (treepath (current engine) (next ?next)) => (retract ?e ?s ?a ?l ?u ?chk) (assert (node ?next)) ) (defrule nAccelerate ; Find how quick the user want's their car (node accelerate) ; Note fast cars are also considered moderate cars in this model, since if the acceleration < 7 then it will also be < 10 and 15! => (printout t crlf "Are you looking for a car with acceleration that is (0-60mph): " crlf " (1) really fast (<7secs)," crlf " (2) moderate(<10secs)," crlf " (3) semi-moderate(<15secs)," crlf " (4) don't know." crlf " Answer [1-4]: ") (assert (answer (read))) (assert (node checkanswer)) ) (defrule nBadAccelerate ; Check input is valid, if not display again (declare (salience 0)) ?chk <- (node checkanswer) ?n <- (node accelerate) ?ans <- (answer ?a) (or (test (< ?a 1)) (test (> ?a 4)) ) => (printout t crlf "*** Bad Answer, please reanswer question ***" crlf crlf) (retract ?ans ?chk ?n) (assert (node accelerate)) ) (defrule nAccelerateMatches1 ; Like Engine size we need to set an upper limit so we can eliminate those cars that don't match, (declare (salience 1)) ; but we needn't set a lower limit given the note in nAccelerate. ?e <- (node accelerate) (answer 1) => (assert (upper 7)) (assert (node accelerateset)) (retract ?e) ) (defrule nAccelerateMatches2 ; Set limits for speed (declare (salience 1)) ?e <- (node accelerate) (answer 2) => (assert (upper 10)) (assert (node accelerateset)) (retract ?e) ) (defrule nAccelerateMatches3 ; Set limits for speed (declare (salience 1)) ?e <- (node accelerate) (answer 3) => (assert (upper 15)) (assert (node accelerateset)) (retract ?e) ) (defrule nAccelerateMatches4 ; Set limits for speed, although user doesn't care so anything with a 0 - 60mph of < 1000 will suit! (declare (salience 1)) ?e <- (node accelerate) (answer 4) => (assert (upper 1000)) (assert (node accelerateset)) (retract ?e) ) (defrule nAccelerateRejects-1 ; Compare remaining cars to limits on speed set above (declare (salience 1)) (node accelerateset) (upper ?up) ?c <- (car (manufacturer ?manuf) (model ?model) (acceleration ?ac)) (test (> ?ac ?up)) => (retract ?c) ;(printout t "Removing " ?model ", " ?ac ", " ?up crlf) (assert (node acceleratecleanup)) ) (defrule nAccelerateRejects-2; catch all incase none were eliminated above (declare (salience 0)) (node accelerateset) => (assert (node acceleratecleanup)) ) (defrule nAccelerateCleanup ; Clean up assertions made in accelerate ?e <- (node acceleratecleanup) ?s <- (node accelerateset) ?a <- (answer ?x) ?u <- (upper ?z) ?chk <- (node checkanswer) (treepath (current accelerate) (next ?next)) => (retract ?e ?s ?a ?u ?chk) (assert (node ?next)) ) (defrule nQuality ; Find out quality requirements, 1+2 should be handled the same, as should 3+4 (node quality) => (printout t crlf "Is quality: " crlf " (1) the highest concern," crlf " (2) of high concern," crlf " (3) of moderate concern," crlf " (4) don't know." crlf " Answer [1-4]: ") (assert (answer (read))) (assert (node checkanswer)) ) (defrule nBadQuality ; check valid input (declare (salience 2)) ?chk <- (node checkanswer) ?n <- (node quality) ?ans <- (answer ?a) (or (test (< ?a 1)) (test (> ?a 4)) ) => (printout t crlf "*** Bad Answer, please reanswer question ***" crlf crlf) (retract ?ans ?chk ?n) (assert (node quality)) ) (defrule nQualityMatches1 ; check quality against assertions made by rule S in rule set defined above (declare (salience 1)) ; remove those that aren't 'quality' ?e <- (node quality) (or (answer 1) (answer 2) ) ?c <- (car (manufacturer ?manuf) (model ?model)) (not(quality ?manuf ?model)) => ;(printout t "Removing " ?model ", " ?manuf crlf) (retract ?c) (assert (node qualitycleanup)) ) (defrule nQualityMatches2 ; Catch all other outcomes from quality question, i.e. none matched above. (declare (salience 0)) ?e <- (node quality) => (assert (node qualitycleanup)) ) (defrule nQualityCleanup ; clean up assertions made by quality routines ?n <- (node quality) ?a <- (answer ?x) ?chk <- (node checkanswer) ?s <- (node qualitycleanup) (treepath (current quality) (next ?next)) => (retract ?n ?s ?a ?chk) (assert (node ?next)) ) (defrule nReliability ; Establish reliability requirements (node reliability) => (printout t crlf "Is reliability: " crlf " (1) the highest concern," crlf " (2) of high concern," crlf " (3) of moderate concern," crlf " (4) don't know." crlf " Answer [1-4]: ") (assert (answer (read))) (assert (node checkanswer)) ) (defrule nBadReliability ; Check for bad answer (declare (salience 0)) ?chk <- (node checkanswer) ?n <- (node reliability) ?ans <- (answer ?a) (or (test (< ?a 1)) (test (> ?a 4)) ) => (printout t crlf "*** Bad Answer, please reanswer question ***" crlf crlf) (retract ?ans ?chk ?n) (assert (node reliability)) ) (defrule nReliabilityMatches1 ; check reliability against assertions made by rules A, B and C in rule set above (declare (salience 1)) ; remove those that aren't 'reliable' ?e <- (node reliability) (or (answer 1) (answer 2) ) ?c <- (car (manufacturer ?manuf) (model ?model)) (not(reliable ?manuf ?model)) => ;(printout t "Removing " ?model ", " ?manuf crlf) (retract ?c) (assert (node reliabilitycleanup)) ) (defrule nReliabilityMatches2 ; Catch all - Reliability (declare (salience 1)) ?e <- (node reliability) => (assert (node reliabilitycleanup)) ) (defrule nReliabilityCleanup ; Clean up all assertions made by Reliability check ?n <- (node reliability) ?a <- (answer ?x) ?chk <- (node checkanswer) ?s <- (node reliabilitycleanup) (treepath (current reliability) (next ?next)) => (retract ?n ?s ?a ?chk) (assert (node ?next)) ) (defrule nCountry (node country) => (printout t crlf "Do you prefer cars made in a particular country?" crlf " Answer [Y/N]: ") (assert (answer (read))) (assert (node checkanswer)) ) (defrule nCountryCheckAnswer (declare (salience 0)) ?chk <- (node checkanswer) ?n <- (node country) ?ans <- (answer ?a) (not (or (test (eq ?a Y)) (test (eq ?a N)) (test (eq ?a y)) (test (eq ?a n)) ) ) => (printout t crlf "*** Bad Answer, please reanswer question ***" crlf crlf) (retract ?ans ?chk ?n) (assert (node country)) ) (defrule nCountryGetCountryName (declare (salience 1)) ?chk <- (node checkanswer) ?n <- (node country) ?ans <- (answer ?a) (or (test (eq ?a Y)) ;(test (eq ?a N)) (test (eq ?a y)) ;(test (eq ?a n)) ) => (printout t crlf "Enter preferred country of manufacture: ") (retract ?ans ?chk) (assert (answer (read))) (assert (node matchcountry)) ) (defrule nCountryGetCountryName-2 (declare (salience 1)) ?chk <- (node checkanswer) ?n <- (node country) ?ans <- (answer ?a) (or (test (eq ?a N)) (test (eq ?a n)) ) => (retract ?chk ?ans) (assert (node countrycleanup)) ) (defrule nMatchCountry ; Remove non-matching cars from list (declare (salience 2)) ?m <- (node matchcountry) ?ans <- (answer ?a) ?c <- (car (manufacturer ?manuf) (model ?model) (coManuf ?co)) (test (neq ?co ?a)) => (retract ?c) (assert (node countrycleanup)) ) (defrule nCountryCleanup1 ; County name has been entered, and searched ?n <- (node matchcountry) ; Also Clean up assertions used by Country ?m <- (node countrycleanup) ?c <- (node country) ?a <- (answer ?p) (treepath (current country) (next ?next)) => (retract ?m ?c ?a ?n) (printout t crlf "Matches" crlf "-------" crlf) (assert (node ?next)) ) (defrule nCountryCleanup2 ; The other situation where Prefered country reply is N ?m <- (node countrycleanup) ?c <- (node country) (not (answer ?p)) (treepath (current country) (next ?next)) => (retract ?m ?c) (printout t crlf "Matches" crlf "-------" crlf) (assert (node ?next)) ) (defrule nFinal1 ; The end, display the matching cars (declare (salience 5)) (node final) (car (manufacturer ?manuf)(model ?model)) => (printout t ?manuf " " ?model crlf) (assert (node goagain)) ) (defrule nFinal2 ; Catch the last stage where no cars match (declare (salience 2)) ?n <- (node ?x) (test (neq ?x final)) ?f <- (node final) (not(car (manufacturer ?manuf)(model ?model))) => (printout t crlf "No cars match your requirements." crlf) (assert (node goagain)) (retract ?n ?f) ) (defrule nEmpty ; No Cars match the input so far, strart again? (declare (salience 10)) (not (car (manufacturer ?manuf) (model ?model))) (not (init)) => (assert (node final)) ) (defrule nGoAgain ; find out if the user wants to go again. (declare (salience 4)) ; Called at the end of every run through the tree (node goagain) => (printout t crlf "Restart? [Y/N]: ") (assert (goagain (read))) (printout t crlf crlf crlf) ) (defrule nProcGoAgain ; If the user says Y or y then start again ?g <- (node goagain) ?ans <- (goagain ?a) (or (test (eq ?a y)) (test (eq ?a Y)) ) => (retract ?g ?ans) (reset) ) (defrule nProcGoAgain2 ; if the user doesn't say y or Y then end ?g <- (node goagain) ?ans <- (goagain ?a) (not (or (test (eq ?a y)) (test (eq ?a Y)) ) ) => (clear) ) (reset) ; clear Jess KB (run) ; Start it all begining, ensures always starts at load up.