NeoClassic Knowledge Representation System Tutorial (Part 2)

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 lab-asg1.txt in the same session, type:

>>> (readFile "<topdir>/Helper/meal-foods.Neo")

otherwise type:

>>> (readFile "<topdir>/Recover/after-meal-food.Neo")


In the previous module of this assignment we covered:
  1. How to create disjoint-primitive concepts. 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. How to define roles and attributes.
  4. How to create individuals, and when role restrictions will make the description of an individual inconsistent.


The next parts of the KB that we will start fleshing out are the WINE-REGIONs and the WINERYs, as represented in ``
wine-region'' and `` wineries''. The two concepts are structurally very simple: WINE-REGIONs and WINERYs are simply individuals that belong to WINE-REGION or WINERY, respectively. The following is typical of the definitions of WINE-REGIONs:

>>> (createIndividual Medoc WINE-REGION)

Type this in.

Now, create another WINE-REGION called Bordeaux. And another one called Napa-Valley.

The WINERYs are created in a similar way. Create a WINERY called Kalin-Cellars and one called Forman.

You can verify that the above individuals are in the KB using the NeoClassic function "getClassicIndividuals". Do it.

Remember, you can never delete an individual from the KB, unless you decide to remove all the existing individuals from all KB's using the function called reinitCollection -- don't enter this command, unless you want to remove all the individuals that you have created so far.

On the other hand, you can remove some information from an individual using the function "removeToldInformation". Whenever an individual is modified through deletion or addition of information, NeoClassic will reclassify it using the new definition.

For instance, print the information that NeoClassic knows about the individual Medoc. Now, try to retract the fact that Medoc is a WINE-REGION. Once you are done, print Medoc again. You will see that its direct parent is now ClassicThing instead of WINE-REGION.

We will not go through the definition of all the instances of WINE-REGION, WINERY and MEAL-FOOD. They are in separate files which you will need to load; but you needn't look at the files unless you want to.

Load the files now.

>>> (readFile "<topdir>/Helper/wineries-and-regions.Neo")

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

You can verify that the instances of WINERY and WINE-REGION have been created properly by using the "getDirectInstances" command on WINERY and WINE-REGION. Try it.


Suppose we are not satisfied with the very flat classification of wineries that we now have, and would like them to be organized by region. We are going to do this in 3 steps:
  1. We will first create subclasses of WINE-REGION.
  2. Using these, we will create subclasses of WINERY.
  3. Finally we will add some information to the individual wineries that will allow them to be classified by region.

The goal is to refine the concept WINE-REGION into 3 subclasses: FRENCH-WINE-REGION, AMERICAN-WINE-REGION and OTHER-EUROPEAN-WINE-REGION.

We want FRENCH-WINE-REGION to be a WINE-REGION that is one of Bordeaux, Bourgogne, Beaujolais, Loire, and Medoc. Try to define this new concept, using the "oneOf" construct.

Now examine the instances of FRENCH-WINE-REGION. You should find the five regions listed.

Let's pause for a moment to examine how enumerative definitions work.

First, verify using "isClassicIndividual" that there is no individual Charlie in your NeoClassic KB. Now, define a concept C1 using a slightly different version of the definition for the FRENCH-WINE-REGION concept, which contains Charlie as another member of the list of WINE-REGIONs. Notice that NeoClassic does not complain about your definition! Check the KB again with "getClassicIndividuals". What has NeoClassic done? (Put a brief commented answer in your file.) Evidently, NeoClassic can be accommodating about some definitions that invoke as-yet undefined individuals.

Second, examine the instances of C1. Explain why Charlie is not an instance of C1. (Comment out your answer.)

Third, define a new concept C2: C2 is a ClassicThing that is one of Bordeaux, Bourgogne, Beaujolais, Loire, and Medoc. Examine this concept; note that NeoClassic knows that every possible instance of C2 is a WINE-REGION, but doesn't seem to know that C2 is a WINE-REGION. Can you give an account of what is going on here? (Comment out your answer.) Can you explain why NeoClassic doesn't classify C2 under WINE-REGION? (If you have trouble answering this, consult "Living with CLASSIC," Section 4.3, "Concepts and Individual Processing".)

Now, let's continue building the knowledge base.

AMERICAN-WINE-REGION is defined in a similar way to FRENCH-WINE-REGION, with the instances Napa-Valley, Sonoma, Santa-Cruz-mountains, and Santa-Barbara. Define this concept before you go on.

OTHER-EUROPEAN-WINE-REGION includes the regions that are not part of the other classifications. Since NeoClassic doesn't have a "NOT" construct, we will have to use exhaustive enumeration to capture the other regions, i.e. Alsace, Chianti, Piemont. Define the concept before going on.

(If you haven't been able to define these concepts by yourself, look at file ``<topdir>/Recover/until-regional-winery.Neo ''.)

Check that the non-French wine region instances were correctly classified under the newly created concepts.


Next you'll create a concept REGIONAL-WINERY which is defined to be a WINERY with a region role filled by exactly one WINE-REGION. Don't do it yet! Read on first. Remember that you need to define roles before you can use them. See the section of the NeoClassic User's Guide entitled "Roles" for further explanation of roles and how to define them. Also remember that WINERY is a primitive, so REGIONAL-WINERY will have to be explicitly asserted to be a WINERY.


(If you are really lost about how to do it, see the file ``<topdir>/Recover/after-regional-winery.Neo ''.)

Check that everything worked as it should by calling the function printInfo. The description that you get should look exactly like this.

======================== ClassicConcept ========================
|| Name:                   REGIONAL-WINERY
||    Primitive:           false
||    Primitives:          {WINERY}
||    Rules:               {}
|| Ingredients:
||    Told Parents:        {WINERY}
||    Components:          {(atLeast 1 region), (all region WINE-REGION)}
|| Taxonomy:
||    Parents:             {WINERY}
||    Children:            {}
||    DirectInstances      {}
|| Soup:
||    Primitive Ancestors: {WINERY}
||    One of:              {}
||    RoleRestrictions:    {<region 1-1 {} WINE-REGION>}
||    Tests:               {}
||    Incoherent?          false
Remember that there are two ways for imposing the required "exactly one" number restriction on the role region of REGIONAL-WINERY.
  1. You can define region as an attribute. This will automatically set up an "atMost 1" restriction for each concept that has region as a role. Thus, when you define a concept like REGIONAL-WINERY that should have one and only one region, you will only need to declare an "atLeast 1" restriction in the definition; NeoClassic will automatically infer the "atMost 1" restriction from the fact that region is an attribute.
  2. You can define region as a role. This will require you to add appropriate "atMost" restrictions in the definitions of concepts that have region as a role, as these definitions come up.
The decision between the above alternatives depends upon whether different concepts may vary in the "atMost" restrictions they impose on the role. In general, a certain role may function as an attribute for all concepts in the domain, or it may function as an attribute only for some. In our example, if we are sure that we will never add any multi-regional wineries (wineries that operate in more than one wine region) to the domain, we could safely declare the role region to be an attribute. But we have to be careful about such decisions; we do need to be very sure that we will never want to include multi-regional wineries in our knowledge base. If we ever decide to retract our decision to make region an attribute, we will have to go through the knowledge base by hand and rebuild it so that the desirable consequences that followed from making region an attribute are preserved in the new KB, while the undesirable ones are discarded. This may well be a complicated procedure if the KB is at all large, and we are liable to make mistakes.

In our KB, we are, in fact, very sure that all the wineries will have at most one associated region. Therefore, we can define region as an attribute in order to avoid including the "atMost 1" restriction in the definition of WINERY.

You can check whether you made region an attribute typing

>>> (isAttribute region).

If you did not make region an attribute, you should change it, since the definitions supplied in our Helper files will assume that it is an attribute. To do this, you can type

>>> (readFile "<topdir>/Recover/after-regional-winery.Neo")

You might want to look at the file ``<topdir>/Recover/until-wineries.Neo'' to see what you would have needed to do if region had not been an attribute.

NeoClassic will automatically infer that an instance of WINERY is a regional winery as long as it is able to show that the instance has at least one region. To illustrate this, first create an individual My-Winery, which is a WINERY with the region role filled by Chianti. Test that in fact NeoClassic classifies My-Winery as a regional winery. Second, try to create an individual Impossible-Winery that is a REGIONAL-WINERY and yet cannot have any regions. Note the response that you get from NeoClassic when you try to do this.

Now that we have the concept of REGIONAL-WINERY, let's use it. First, we will create several child concepts of REGIONAL-WINERY, namely FRENCH-WINERY, AMERICAN-WINERY and OTHER-EUROPEAN-WINERY, so that we can eventually classify all the wineries under these concepts.

Define the three concepts now.

(If you are really confused at this point, look at file ``<topdir>/Recover/until-wineries.Neo''.) Once the concepts are defined, print one of them to make sure that NeoClassic is understanding you properly.

In common sense language and reasoning, we often presuppose the existence of role fillers; if I tell you that all Jack's children are in college, for instance, you will assume that Jack has at least one child. But in logic, and in many logic-based Knowedge Representation (KR) systems, including NeoClassic, these so-called "existential presuppositions" will not be made by the system unless they are declared explicitly. (Recall that in First-Order Logic, "All Jack's children are in college" will be true if Jack has no children.) Because of this discrepancy between common sense and First-Order Logic, it's easy to forget to declare explicitly that an attribute must have some fillers. To drive this point home, create a temporary individual No-Regions that is a WINERY with at most 0 regions. Print the ancestors of this regionless winery. Briefly explain why NeoClassic returns the information that it does; in particular, why doesn't NeoClassic treat No-Regions as a REGIONAL-WINERY? Comment out your answer.

You should now be able to tell why we defined FRENCH-WINERY as we did, rather than saying that a FRENCH-WINERY is a WINERY with all its region's FRENCH-WINE-REGIONs. NeoClassic would then not have classified FRENCH-WINERY under REGIONAL-WINERY. To test this, define a concept C3 to be a WINERY with all its regions FRENCH-WINE-REGIONs. Does NeoClassic place C3 under REGIONAL-WINERY? Verify this using NeoClassic. You shouldn't be surprised that it doesn't; explain why NeoClassic doesn't think that C3s are REGIONAL-WINERIES, commenting out your answer. (Hint: print the ancestors of No-Regions.)


Now we have all the concepts we need to properly classify the instances of WINERY by region. In order to do this we will need to add region information to each instance of WINERY. Since there are lots of wineries, we'll only ask you to do this for a couple of them.

There are a number of functions for adding information to an individual. The NeoClassic User's Guide shows these in the "Addition" section under the section called "Updates". We will need to add both a role and its filler. The function to use is called "addToldInformation." Let's take the winery Forman as an example. We want to add the information that its region is Napa-Valley. Look at the documentation for addToldInformation and try that now. (Hint: use fills.) If you absolutely can't do it by yourself, look at the file ``<topdir>/Helper/winery-region-info.Neo''.

After you have added the information to Forman, check that the system classifies it as an AMERICAN-WINERY.

IMPORTANT: remember, you can always add information to or remove information from individuals, but you can never delete an individual from the KB or modify an existing concept, other than by reloading the knowledge base. For this reason, you have to be cautious when adding concepts to the NeoClassic KB.


We won't make you go through all the wineries. But you might look at the file ``<topdir>/Helper/winery-region-info.Neo'' to see what's in it.
Then type:
>>> (readFile "<topdir>/Helper/winery-region-info.Neo")

Use NeoClassic functions to determine the instances of FRENCH-WINERY and of OTHER-EUROPEAN-WINERY.

Save and close your shell file which is logging your input now.


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