/* V I N E Version 2.1 Copyright (c) Teknowledge Inc, 1986 December 10, 1986 */ /* This knowledge base contains the same knowledge as WINE, but uses logical variables (denoted by capital letters) so that syntactically identical rules from the WINE knowledge base can be collapsed into a single rule in VINE. In addition, VINE uses logical variables in conjunction with a small database of wines, and a single 'table lookup' rule to find the wines, rather than a separate rule for each wine. */ /* The top-level goal of the consultation is 'wine'. */ goal = wine. /* Before the system attempts any inferences, the user's preferences are obtained: */ initialdata = [preferred-color, preferred-body, preferred-sweetness]. /* --------------------------- BEST-BODY ------------------------------- */ /* The following rules use information about the sauce on the meal and the meal's tastiness to find the best body for the wine. */ rule-1: if has-sauce and sauce = spicy then best-body = full. rule-2: if tastiness = delicate then best-body = light cf 80. rule-3: if tastiness = average then best-body = light cf 30 and best-body = medium cf 60 and best-body = full cf 30. rule-4: if tastiness = strong then best-body = medium cf 40 and best-body = full cf 80. rule-5: if has-sauce and sauce = cream then best-body = medium cf 40 and best-body = full cf 60. /* --------------------------------- BEST-COLOR -------------------- */ /* The following rules use information about the main component of the meal and the sauce on the meal to determine the best color of wine to accompany the meal. */ rule-6: if main-component = meat and has-veal = no then best-color = red cf 90. rule-7: if main-component = poultry and has-turkey = no then best-color = white cf 90 and best-color = red cf 30. rule-8: if main-component = fish then best-color = white. rule-9: if not(main-component = fish) and has-sauce and sauce = tomato then best-color = red. rule-10: if main-component = poultry and has-turkey then best-color = red cf 80 and best-color = white cf 50. rule-11: if has-sauce = yes and sauce = cream then best-color = white cf 40 and best-color = red cf -90. /* -------------------------- BEST-SWEETNESS -------------------------- */ /* The only rule that can help provide information about how sweet the recommended wines should be 'fires' when the meal has a sweet sauce on it. */ rule-12: if has-sauce and sauce = sweet then best-sweetness = sweet cf 90 and best-sweetness = medium cf 40. /* ----------------------- DEFAULT-X --------------------------------- */ /* These default expressions are used when M.1 is unable to find values for either best-CHARACTERISTIC or preferred-CHARACTERISTIC. The single 'noautomaticquestion' entry keeps M.1 from ever asking the user to provide a value for a default characteristic. */ noautomaticquestion(default-X). default-body = medium. default-color = red cf 50. default-color = white cf 50. default-sweetness = medium. /* ----------------------- FEATURE ----------------------------------- */ /* 'Feature' is a special characteristic of wine, currently used only to indicate that the meal is spicy. */ multivalued(feature). rule-13: if has-sauce and sauce = spicy then feature = spiciness. /* ----------------------------- HAS-SAUCE --------------------------- */ /* We used 'automaticmenu' without 'enumeratedanswers' to get a menu of 'legalvals' with no numbers assigned to them. */ question(has-sauce) = 'Does the meal have a sauce on it?'. legalvals(has-sauce) = [yes, no]. automaticmenu(has-sauce). /* ---------------------------- HAS-TURKEY ---------------------------- */ /* We used 'automaticmenu' without 'enumeratedanswers' to get a menu of 'legalvals' with no numbers assigned to them. */ question(has-turkey) = 'Does the meal have turkey in it?'. legalvals(has-turkey) = [yes, no]. automaticmenu(has-turkey). /* ---------------------------- HAS-VEAL ------------------------------- */ /* We used 'automaticmenu' without 'enumeratedanswers' to get a menu of 'legalvals' with no numbers assigned to them. */ question(has-veal) = 'Does the meal have veal in it?'. legalvals(has-veal) = [yes, no]. automaticmenu(has-veal). /* ---------------------------- MAIN-COMPONENT ------------------------- */ /* The 'question' for main-component contains a more informative menu than that produced by the 'automaticmenu' meta-fact. Note that spacing and carriage returns within the question are respected by M.1. */ multivalued(main-component). enumeratedanswers(main-component). automaticmenu(main-component). question(main-component) = 'What is the main component of the meal?'. legalvals(main-component) = [meat, fish, poultry]. /* ----------------------------- PREFERRED-X --------------------------- */ /* These meta-facts contain logical variables (in capital letters) that allow these meta-facts to apply when seeking preferred-color, preferred-body, and preferred-sweetness. */ enumeratedanswers(preferred-X). automaticmenu(preferred-X). /* --------------------------- PREFERRED-BODY -------------------------- */ multivalued(preferred-body). question(preferred-body) = 'Do you generally prefer light, medium or full bodied wines?'. legalvals(preferred-body) = [light, medium, full]. /* -------------------------- PREFERRED-COLOR -------------------------- */ multivalued(preferred-color). question(preferred-color) = 'Do you generally prefer red or white wines?'. legalvals(preferred-color) = [red, white]. /* -------------------------- PREFERRED-SWEETNESS ---------------------- */ multivalued(preferred-sweetness). question(preferred-sweetness) = 'Do you generally prefer dry, medium or sweet wines?'. legalvals(preferred-sweetness) = [dry, medium, sweet]. /* -------------------------- RECOMMENDED-X ------------------------- */ /* These rules contain logical variables (in capital letters) that make these rules applicable when seeking best-color, best-body, and best-sweetness. If best-CHARACTERISTIC is known, then that is what's recommended. If the user's preference about a particular characteristic is known, then that's used as the recommended characteristic. If neither the best nor the preferred characteristic is known, then a default value is used. */ v-rule-1: if best-X = V then recommended-X = V. v-rule-2: if best-X is unknown and preferred-X = V then recommended-X = V. v-rule-3: if best-X is unknown and preferred-X is unknown and default-X = V then recommended-X = V. /* -------------------------- SAUCE ---------------------------------- */ /* 'automaticmenu' and 'enumeratedanswers' are used to generate a numbered menu of 'legalvals' for this question. */ multivalued(sauce). question(sauce) = 'What kind of sauce does the meal have?'. legalvals(sauce) = [spicy, sweet, cream, tomato]. automaticmenu(sauce). enumeratedanswers(sauce). /* ------------------------- TASTINESS ------------------------------- */ multivalued(tastiness). question(tastiness) = 'Is the flavor of the meal delicate, average or strong?'. legalvals(tastiness) = [delicate, average, strong]. /* ----------------------------- WINE ------------------------------ */ multivalued(wine). multivalued(wine(COLOR,BODY,SWEETNESS)). /* The following rule, with the table entries that follow, replaces the bulk of the rules from the wine KB that conclude wine: */ v-rule-4: if recommended-color = C and recommended-body = B and recommended-sweetness = S and wine(C,B,S) = W then wine = W. /* The following rule mentions feature, and hence is inconvenient to replace by a table-entry. */ rule-14: if recommended-color = white and recommended-body = full and feature = spiciness then wine = gewuerztraminer. /* ----------------- WINE(COLOR, BODY, SWEETNESS) ------------------ */ /* This 'noautomaticquestions' statement ensures that no automatic question will be generated for wines not included in this table. */ noautomaticquestion(wine(COLOR,BODY,SWEETNESS)). /* These table entries represent the mapping of attribute triples to specific wines. Note the use of the variable ANY in some entries to indicate that a particular attribute doesn't play a role in the selection of that wine: */ wine(red,medium,medium) = gamay. wine(red,medium,sweet) = gamay. wine(white,light,dry) = chablis. wine(white,medium,dry) = 'sauvignon blanc'. wine(white,medium,dry) = chardonnay. wine(white,medium,medium) = chardonnay. wine(white,full,dry) = chardonnay. wine(white,full,medium) = chardonnay. wine(white,light,dry) = soave. wine(white,light,medium) = soave. wine(white,light,medium) = riesling. wine(white,light,sweet) = riesling. wine(white,medium,medium) = riesling. wine(white,medium,sweet) = riesling. wine(white,light,medium) = 'chenin blanc'. wine(white,light,sweet) = 'chenin blanc'. wine(red,light,ANY) = valpolicella. wine(red,ANY,dry) = 'cabernet sauvignon'. wine(red,ANY,dry) = zinfandel. wine(red,ANY,medium) = 'cabernet sauvignon'. wine(red,ANY,medium) = zinfandel. wine(red,medium,medium) = 'pinot noir'. wine(red,full,ANY) = burgundy. /* ----------------------------------------------------------------------- */