NeoClassic Knowledge Representation System Tutorial (Part 4)

Copyright AT&T 1996

Here is the text version


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

If you are continuing from Part 3 in the same session, type

>>> (readFile "<topdir>/Helper/just-wines.Neo ")

or type

>>> (readFile "<topdir>/Recover/after-just-wines.Neo ") to recover state.

Otherwise, if this is a new session, type:

>>> (readFile "<topdir>/Recover/after-just-wines.Neo ") These loading operations may take a bit of time because they are adding many wine individuals to the KB.

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

REVIEW OF Part 1, Part 2 and Part 3

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.
You may want to review some of these topics.


Definitions can help to organize knowledge, but most useful domain information does not follow from concept definitions alone. NeoClassic provides rules as a way to extend our knowledge of individuals, by adding information that can't be inferred from the definitions of the concepts under which the individuals are classified, but that will nonetheless be expected or known. In the last module we saw how rules can be used for this purpose.

In this module we will look at some other uses for rules. You might want to briefly review the end of asg3.txt before proceeding.


We have seen that the "oneOf" restriction construct can be used to define a concept as a disjunction of individual instances. The definition of WINE-FLAVOR in Part 1 is an example.
	WINE-FLAVOR (and WINE-PROPERTY (oneOf Delicate Moderate Strong)))
However, there is no general way in NeoClassic to define a concept as a disjunction of several other concepts. For instance, there is no direct way to define a concept of DELICATE-OR-WHITE-WINE. Disjunction is intentionally limited in NeoClassic.

Despite these limitations, we can often use rules to achieve some of the effects of disjunctive concepts. "Dirty tricks" of this sort are of course risky, but they can be useful. We will use an example to illustrate the use of rules to imitate disjunctive concepts.

We know that in many cases, a concept is (implicitly) a disjunction of its children concepts. Suppose you want to define a primitive concept MY-FAVORITE-WINE whose only restrictions are that it must be either a CHARDONNAY or an ITALIAN-WINE. There is no straightforward way in NeoClassic of expressing this restriction using the constructs for defining primitive concepts. But we can use rules to approximate the disjunctive concept that we want in the definition, as follows.

  1. Create a primitive concept MY-FAVORITE-WINE under WINE. (The concept has to be primitive because there is nothing definitional distinguishing it from its parent concept WINE.)
  2. Add rules to CHARDONNAY and ITALIAN-WINE asserting that any instance of each of these concepts should also be an instance of MY-FAVORITE-WINE. (Note that this information is certainly not definitional for either CHARDONNAY or ITALIAN-WINE.)
This is only an approximation of true disjunction for several reasons. For instance, if we create an individual My-Wine and tell NeoClassic that it is a MY-FAVORITE-WINE with its region filled by Sonoma, NeoClassic will not infer that it is a CHARDONNAY. Moreover, if we create another individual, My-wine2, and tell NeoClassic that it is MY-FAVORITE-WINE and a BORDEAUX-WINE, NeoClassic will not detect the inconsistency.

You can think of it this way: this trick will in general provide sufficient conditions for classifying something under MY-FAVORITE-WINE, but it won't provide necessary conditions.

Try to implement the idea, in the following steps.

  1. Create the concept MY-FAVORITE-WINE.
  2. Show that there are no instances under the new concept.
  3. Add the appropriate rules to CHARDONNAY and ITALIAN-WINE and show that the concepts now have them. You can use "getRules" on the concept for this.
  4. Show that MY-FAVORITE-WINE now has the appropriate instances.
To recover state here, use: (readFile " <topdir>/Recover/after-just-wines.Neo")


This section introduces a use for rules that extends the type of reasoning you might think NeoClassic is capable of doing. The definitions and rules are in file: ``
<topdir>/Helper/food-wines.Neo''. Look at the file, if you wish, then type:

>> (readFile " <topdir>/Helper/food-wines.Neo")

The "food-wines.Neo" knowledge base contains examples like the following ones, which provide information about wines appropriate for spicy-red-meat food. Do NOT enter these commands; they were included in the file you just loaded.

(createRule spicy-red-meat-wine-color SPICY-RED-MEAT
	     (all appropriate-drink (fills color Red)))
(createRule spicy-red-meat-wine-body SPICY-RED-MEAT
	     (all appropriate-drink (fills body Full)))
(createRule spicy-red-meat-wine-flavor SPICY-RED-MEAT
	     (all appropriate-drink (fills flavor Moderate)))
(createRule spicy-red-meat-wine-sugar SPICY-RED-MEAT
	     (all appropriate-drink (fills sugar Dry)))
Note that the rules associated with a food concept impose a number of restrictions on any wine that fills the appropriate-drink role of an instance of the concept. The rules concentrate on the appropriate-drink role because we are assuming that the knowledge base we are building would be used to give advice in selecting drinks to go with certain foods. If we were interested in other kinds of advice (suitability for certain sorts of diets, for instance), we would have to modify the food concept by adding appropriate roles, and would need to add rules constraining these roles. You'll see below how these rules are used.

Suppose we want to find out what wines go with a SPICY-RED-MEAT food. We first create a meal course that is a SPICY-RED-MEAT.

>>> (createIndividual My-Meal-Food 
                   (and SPICY-RED-MEAT (fills appropriate-drink Some-Wine)))
Create My-Meal-Food using this definition, and use "printInfo" to inspect it. You will notice that the role "appropriate-drink" has restrictions associated with it, that were created by the rules for SPICY-RED-MEAT.

These restrictions represent what we know about a wine, when we are told that it is appropriate with any instance of SPICY-RED-MEAT. Manually browse through the knowledge base for an individual wine that meets all these restrictions, and an individual instance of SPICY-RED-MEAT. Do you expect NeoClassic to know that the wine is appropriate for the meat? Make your prediction now, and then query NeoClassic for the answer. Explain why NeoClassic gives the result it does, and test your prediction, before reading the answer.

But even the most open domains can have parts that are closed; and it is often very useful in special cases to simulate closed-world reasoning. The case of SPICY-RED-MEAT is a good example. It is reasonable to expect here that we have listed all the conditions that make a wine appropriate for a SPICY-RED-MEAT, so that a wine that satisfies them will in fact be a good recommendation for a meal featuring SPICY-RED-MEAT. In fact, it is hard to see how we can use the knowledge we have put into the system to make useful meal-planning suggestions without making some assumption of this sort.

To explore how to do this, let's return to the individual My-Meal-Food that we created above. Remember that the role "appropriate-drink" has only the restrictions that follow from assuming that a wine goes with SPICY-RED-MEAT. What we need to know now is, which individual wines in our knowledge base satisfy these restrictions. For this we can use the function "getInstances" in the following way. (An explanation of this function is in the NeoClassic Reference Manual in the section entitled ``Taxonomy Retrievals''. It can be found under the top level section called "NeoClassic Interface Functionality" and in the section called "Concepts" in there.)

First we create a concept that contains the description.

>> (createConcept MY-WINE1 
       (derivedValueRestriction MY-MEAL-FOOD My-Meal-Food))
Then we can find the instances that satisfy this concept.

>>> (getInstances MY-WINE1)

The function "getInstances" takes a concept. The concept that we need is found in the derivedValueRestriction for the individual, My-Meal-Food, on its appropriate-drink role. The "getInstances" function retrieves the wines that match this concept.

Enter the above command; NeoClassic should return the following answer to your query:

{Mazocco-Zinfandel, Some-Wine}

Mazocco-Zinfandel is in fact the only wine in our KB that we can recommend with a SPICY-RED-MEAT. Some-Wine was just a variable for that wine.

You can see that techniques like this have to be used with care. We have to recognize the closed-world constraints that went into our recommendation: all we really know is that Mazocco-Zinfandel is not incompatible with SPICY-RED-MEAT. We are hoping that our constraints are complete enough so that any wine that is not incompatible with the constraints will in fact be appropriate.

In the previous example the relationships between MEAL-FOODs and appropriate WINEs have been expressed through rules. And in fact we recommended a WINE as appropriate for SPICY-RED-MEAT without ever actually filling the appropriate-drink role. (You might want to check at this point to verify that Mazocco-Zinfandel still does not fill the appropriate-drink role of Beef-Curry.)


The wines KB/domain doesn't really have much circularity. But suppose you were asked to define the following concepts: CHILD would have to be defined before PARENT and viceversa.

To break the loop, you could:

  1. define PARENT as a person with at least one children and all of whose children are PERSONs;
  2. define CHILD as a PERSON with a parents role all of whose fillers are PARENTs;
  3. add a rule to PERSON that says that every instance of PERSON should also be classified as a CHILD.
Try this.


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