NeoClassic Knowledge Representation System Tutorial (Part 5)

Copyright AT&T 1996

Here is the text version


Open a new shell file (meta-X shell) and name it by saving it.

The knowledge base that we will work with is essentially the one at the start of Part 4. In order to make it easier to peruse what was loaded in, this has all been merged into one file. This new file is basically just ``<topdir>/Recover/after-just-wines.Neo'', expanded to include all the files it loaded. We also added the rules in ``<topdir>/Helper/food-wines.Neo''. The entire file is now in ``<topdir>/Recover/expanded-wines-kb.Neo''. (There are some slight modifications in this file, so be sure to use `` it for this exercise.) Enter this: >>> (readFile "<topdir>/Recover/expanded-wines-kb.Neo") Please be patient. Loading the KB will take some time.

You may want to skip down to the end of the review section if you are continuing from Part 4 in the same session.

REVIEW OF Part 1, Part 2, Part 3

and Part 4.

In the first module of this assignment we covered:

  1. How to create "DISJOINT-PRIMITIVE" concepts. Using this construct we created the concepts WINE-PROPERTY, CONSUMABLE-THING, WINERY, and WINE-REGION. We also constructed the concepts EDIBLE-THING, POTABLE-LIQUID, WINE-COLOR, WINE-BODY, WINE-SUGAR, WINE-FLAVOR, WINE and MEAL-FOOD.
  2. Commands for inspecting and navigating the KB.
  3. Definition of Roles and Attributes.
  4. Creation of individuals and the effect of role restrictions on individuals.

    In the second module of this assignment we covered:

  5. Adding concepts to the KB in such a way that existing concepts and individuals get reclassified under the new concepts (we illustrated this with REGIONAL-WINERY and its children).

    In the third module of this assignment we covered:

  6. Using rules in NeoClassic: enhancing concepts via rules, adding rules. The main use of rules, i.e. for adding non-definitional information to instances that get classified under a concept.

    In the fourth module of this assignment we covered:

  7. More use of rules: using rules to create disjunctive concepts, query templates, and circular definitions.
You may want to review some of these topics.

The purpose of this assignment is to investigate some of the issues involved with debugging and maintaining knowledge bases. While we are primarily interested in your learning the material, we are also interested in how easy or hard it is for you to learn. There are 5 times where you will be asked to time yourself while doing a task. You will not be graded on your times. Please be accurate on times. Please do make sure to include times. If by some chance you forget to time something, make an estimate and note that it was an estimate. You will also be asked to write notes in your shell files at places. You can precede each line with a ; so that the interpreter does not try to evaluate your statements.

There is a 3 part question on one step explanations, a 4 part question on complete explanations of error situations, a 4 part question on pruning settings, and an extra credit question.


In order to effectively develop, use, and extend knowledge bases, we need to be able predict the results of additions and queries. Thus, we should understand the inferences that the system makes. We will first explore the use of explanation functions to aid in this process.

In the last assignment (Part 4), you created My-Meal-Food and explored what was true of the associated wine. We will now go into a bit more detail about some of the inferences NeoClassic makes. Let's investigate how some of the foods in the knowledge base got their restrictions on their appropriate-drink role.

In Part 4, you looked at the restrictions on SPICY-RED-MEAT foods. There are two ways to do this: you could just pick one of the SPICY-RED-MEAT foods in the knowledge base like Beef-curry and examine that or you could create a new SPICY-RED-MEAT food and look at it. Let's define the same SPICY-RED-MEAT food again, and examine it through the explanation functions.

Define My-Meal-Food again as:

>>> (createIndividual My-Meal-Food 
                   (and SPICY-RED-MEAT (fills appropriate-drink Some-Wine)))
Let's investigate Some-Wine again. First print it:

>>>(printInfo Some-Wine)

If we are interested in recommending wines with foods, we would want to figure out why Some-Wine has certain fillers and restrictions for the sugar, flavor, body, and color roles. We could ask for a general explanation of the food as follows:

>>>(explain Some-Wine)

However, since the four roles, which we are interested in, have specific fillers, we can ask specifically how each of the fillers got there by typing:

>>>(explain Some-Wine (fills color Red))
>>>(explain Some-Wine (fills sugar Dry))
>>>(explain Some-Wine (fills body Full))
>>>(explain Some-Wine (fills flavor Moderate))

We see that almost everything of interest on Some-Wine came from a propagation on My-Meal-Food because of restrictions on its appropriate-drink role. The restrictions on My-Meal-Food's appropriate-drink role influence Some-Wine because Some-Wine is known to fill My-Meal-Food's appropriate-drink role, and thus it must satisfy all the accompanying restrictions. The next question is how those restrictions got there at all. To use explanation to determine that, do the following.

First get the Inferences from the explanation. Note that '$' translates to the previous answer and '$$' translates to the one before that. There is also a translation for '$$$'.

>>> (getInferences $)

Get the first of those inferences
>>> (select $ 0)

Get the Antecedents on that inference
>>> (getAntecedents $)

Get the second of those antecedents
>>> (select $ 1)

Explain that antecedent
>>> (explain $)

You can repeat this process for each of the four roles.

Now we see that rule firings account for all the fills restrictions on color, body, flavor, and sugar. So, any SPICY-RED-MEAT food, such as Beef-Curry, should have a Red-Wine as its appropriate-drink because of the red-meat-wine-color rule, a Full-Wine because of the spicy-red-meat-wine-body rule, a Moderate-Wine because of the spicy-red-meat-wine-flavor rule, and a Dry-Wine because of the meat-wine-flavor rule.

Above, we went through a six step explanation, first explaining a role filler for Some-Wine and then explaining a particular role on My-Meal-Food. In this case, we could have actually simplified this process by just choosing a food, like Beef-Curry, and explaining each of the restrictions on its appropriate-drink role, like this:

>>> (explain Beef-Curry (all appropriate-drink (fills color Red)))

Now, let's look at another class of food in the knowledge base. We will consider things that fall under NON-OYSTER-SHELLFISH. Consider Lobster, and suppose that we are interested in the appropriate-drink's color, body, flavor, and sugar roles. Don't bother to create a new food and associate a wine with it, just use Lobster.

Now we will time a task.

Explanation 1.
Put a ; in your shell file and note the time. Now use explain on Lobster to answer why its appropriate-drink role has each restriction on the following roles: color, body, flavor, and sugar.

Note the time that it took you to do this task in your shell file (preceded by a ;)

We are going to time another task. This time please DO NOT use the explanation commands. On another food, Fettuccine-Alfredo, please explain the restrictions on its appropriate-drink's color, body, flavor, and sugar roles. Make sure you time this task. You can use whatever NeoClassic commands you like. (You might consider just printing the food and then looking at the file you loaded to discover what rules, propagations, etc. could have applied.)

Explanation 2.
Put a ; and the time in your shell file. Put your answer in the shell file (starting each line with a ; )

Please note your time in the shell file.

Explanation 3.
Make a note in your shell file about if and when you would rather use the explanation commands and if and when you would rather use some other technique to discover why things happened.


Now we will turn to working with errors. NeoClassic needs to maintain a consistent state at all times. Thus, when someone enters something that is inconsistent with the deductive closure of what NeoClassic knows, NeoClassic notes the inconsistency, provides an error message, and retracts the new information that was inconsistent. That means that if you try to add something that is not legal to a knowledge base, the new object will not be part of the updated knowledge base.

However, NeoClassic does maintain error objects. Thus, if you try to add an object A that will cause an inconsistency somewhere, A will be retracted, but NeoClassic will keep the error object for A around as long as you have a variable set to it. You can set a variable called "myErr" to the error object in the following way:
>>>(set myErr $)

You can now access this error object by using its variable. For instance, you may print the information about this error object by typing:
>>>(printInfo $myErr)

Let's create a food and state that a wine is appropriate with it. We can see if NeoClassic agrees that this wine is appropriate. Suppose that we make a meal food that is SPICY-RED-MEAT and say that we want to drink Forman-Chardonnay with it.

>>>  (createIndividual Meal-Food-1 
	      (fills appropriate-drink Forman-Chardonnay)))
We see that NeoClassic will not add Meal-Food-1 to the knowledge base, since this creates a contradiction. We can examine the problem more closely by printing the error object that is referred to in the error message. Remember that variables are automatically created for the three most recent results but they are only temporary.

>>> (printInfo $)

We look at the color role since the error said that there were problems on that role. We see two fillers for color: White and Red. (And we also see that the color role can have at most 1 filler.) So, we might want to find out how it got each of those fillers. Use explain to find out why the error object has both those fillers for its color role by typing:

>>> (explain $$ (and (fills color White) (fills color Red)))

At this point, we may want to ask followup questions:

  1. Why did the chardonnay-color rule fire?
  2. Why did Meal-Food-1 get its restriction on its appropriate-drink role?
Fortunately, there is a way to get that information, though you have to go through many steps to get it. The steps you will go through are similar to those shown prevously (i.e. explain, getInferences, select and getAntecedents). In the future there will be an explainComplete function that will ask ALL outstanding questions for you until the final answer is either that a rule fired, or that some information was told. (NOTE: you will only want to do an explainComplete when you have a very specific question in mind. Otherwise, too many followup questions will be asked automatically.)

So, Forman-Chardonnay is incoherent because it should have at most 1 filler for its color role. It has two fillers: White and Red. White is a filler because of the chardonnay-color rule. (This rule fired because Forman-Chardonnay is an instance of CHARDONNAY). Its other filler, Red, is there since Forman-Chardonnay fills the appropriate-drink role on Meal-Food-1. Meal-Food-1 has a restriction that requires anything that fills its color role to be Red because of the red-meat-wine-color rule. (This rule fired because Meal-Food-1 is an instance of RED-MEAT.)

Now you will do this for another individual. This will be timed again. Create another meal-food (This time make the food NON-OYSTER-SHELLFISH.) and fill the appropriate-drink role with Mt-Adam-Riesling.

>>>  (createIndividual Meal-Food-2 
	      (fills appropriate-drink Mt-Adam-Riesling)))
This creates another error.
Error handling 1
Note the time in your shell file (preceded by a ;)
Now use the explanation functions to figure out why NeoClassic reported an error. Note the time you finished.

Create another meal-food:

(createIndividual Meal-Food-3 
		(fills appropriate-drink Taylor-Port)))
We will time this again, and now PLEASE DO NOT use the explanation functions to discover why NeoClassic complains about this addition. You can use any functions other than the explanation functions and you can look through the knowledge base. You might consider printing the error object, looking for incoherencies, and then looking through the knowledge base to figure out how the incoherencies occurred.
Error handling 2
Please make sure to note the time in the shell file along with your answer.
Error handling 3
Also, please comment on when you would rather use the explanation functions and when you would rather track things down without them. Put your answer in the shell file.
Error handling 4
You should now be able to extend this exercise to the scenario in assignment 4 where you created an error when you said that Beef-Curry was an instance of FOOD-GOOD-WITH-ANY-RED-WINE. Set up that scenario again. Load the following lines:
>>> (createConcept
>>> (createRule add-red-wines food-good-with-any-red-wine
                    (all appropriate-drink (oneOf (getInstances RED-WINE))))
Now, state that Beef-Curry is an instance of a FOOD-GOOD-WITH-ANY-RED-WINE.

>>> (createIndividual Beef-Curry FOOD-GOOD-WITH-ANY-RED-WINE)

Note the error condition on a previously existing wine in the knowledge base. This is another timed task. Begin timing after you tried to say that Beef-Curry is a FOOD-GOOD-WITH-ANY-RED-WINE. Use the explanation functions to explain why the error situation occurred. Note how long this took you to do in the shell file.

It would be wise to read the section called ``Explanation'' in the "NeoClassic Interface Functionality" section of the NeoClassic Reference Manual. There is one main function called explain which we talked about earlier. It can go through steps explaining how each thing happened, including rule firings. There is also another explanation function called explainSubsumed which takes two arguments, the subsumee and the subsumer. It explains why a concept or an individual is subsumed by a description or concept.

Type: <CTRL>X<CTRL>S to save your shell to a file.


You may want to go back to the NeoClassic page or to the main NeoClassic Tutorial page.