NeoClassic Reference Manual

Copyright AT&T 1994

Here is the text version

NeoClassic Overview

1/ What is Classic?

Classic is a full-featured knowledge representation system based on a small description logic. Being a knowledge representation system, Classic stores a collection of information and determines the consequences of this information. Being based on a description logic, the information stored by Classic consists of statements and other expressions from this description logic and the consequences computed by Classic are those sanctioned by the description logic. Being a full-featured knowledge representation system, Classic allows for both the addition and the retraction of information. Further, Classic can explain how it obtained the consequences it computed.

Classic provides a number of extra-logical features, including multiple knowledge bases, forward-chaining rules, procedural extensions to the description logic in the form of test functions and computed rules, and hooks that allow programs to be informed of the actions that Classic performs.

2/ What is NeoClassic?

NeoClassic is an implementation of Classic in C++. NeoClassic heavily uses C++ object-oriented programming. NeoClassic currently provides two low-level interfaces, a character-based interface (CI) and an application program interface (API). There was a graphical user interface (GUI), but it is no longer working. All interfaces can exercise the full knowledge representation capabilities of NeoClassic.

In the CI commands are given to NeoClassic over a character stream, and responses are given back on another character stream. The syntax for the CI allows two ways of grouping a function with its arguments. Parentheses may be placed around the arguments only or parentheses may be placed around the function name as well as the arguments. Most examples are shown using the second syntax. Many CI functions can take an arbitrary number of arguments that are grouped into a set or list.

In the GUI concepts, roles, rules, and individuals can be created in several ways: a file can be specified and read in; CI commands can be entered; or a dialog box that guides the creation of a concept, role, rule, or individual can be used. Concepts, roles, rules, and individuals can be viewed and changes can be made to them and explanation can be performed on them.

The API to NeoClassic exposes the object-oriented implementation of NeoClassic, but in a way that does not (easily) allow subverting the semantics of NeoClassic objects. There is some functionality that only makes sense using the API, and thus does not show up in the CI.

3/ Running NeoClassic

The easiest way to run neoclassic is to execute a version of neoclassic that reads from the standard input into the character interface and writes to the standard output from the character interface. This version of neoclassic is generally available via the command

neoclassic [<input file>...]

where <input file> is the name of a file containing character interface commands. After reading these files, if any, this version of neoclassic will prompt for more input from the standard input.

When the user is running NeoClassic from a unix system it can be run as a server by adding in a "-s" followed by an optional number of seconds after which it should time out, if there is no response. The filename, if there is one, is always the last argument. The default amount of time that the server will wait for a response from the client is 500 seconds. Let us say that a user wants to run NeoClassic as a server that waits only 30 seconds for a response from the client and read in the file "test.classic". The user would call it like this:

neoclassic -s 30 test.classic

The easiest way to run NeoClassic under Windows 95 or Windows NT is to double click on the executable file. Once the window for NeoClassic is up files can be read by using the files menu.

Using NeoClassic as part of a larger C++ program is only slightly more complicated. To compile a C++ program that uses NeoClassic, put the NeoClassic directory in the include path, and include the file NeoClassic.H in each file that uses NeoClassic classes. To link a C++ program that uses NeoClassic, add the library libneoclassic.a to the libraries of the program. The C++ program is responsible for starting NeoClassic by calling the function NeoEnvironment::init and for cleaning up after all use of NeoClassic is done by calling NeoEnvironment::cleanup. To process NeoClassic character interface commands, use the function NeoEnvironment::readFile.

4/ Knowledge Level Overview of NeoClassic

This overview ignores the exact syntax (and semantics) of NeoClassic, in favor of providing a general idea of what NeoClassic can do. A passing familiarity with description logics is required.

NeoClassic allows the creation of a collection of (named) knowledge bases. Each knowledge base has a collection of (named) roles, (named) concepts, (named) individuals, and (named) rules.

The allowable operations on knowledge bases are:

  1. adding information to a knowledge base
    • defining a role
    • defining a concept (in terms of a description)
    • creating a rule (in terms of a concept and a description)
    • creating an individual (in terms of a description)
    • adding information (in the form of a description) to an individual
    • closing a role on an individual
  2. retracting information from a knowledge base
    • removing information (in the form of a description) from an individual
    • unclosing a role on an individual
    • removing a rule (not implemented yet)
  3. querying information in the knowledge base
    • determining whether one description subsumes another
    • determining whether an individual satisfies a description
    • retrieving the information told about an individual or concept
    • retrieving the information derived about an individual or concept
    • traversing the taxonomy of concepts and classic individuals
NeoClassic immediately computes the consequences of all information added to a knowledge base. If an attempt is made to define an incoherent concept (i.e., a concept that could never have any instances) then the attempt is rejected. If an attempt is made to change a knowledge base in a way that would make the knowledge base inconsistent then that attempt is rejected. In both the above cases information is returned indicating why the attempt was invalid.

NeoClassic is not quite a complete reasoner. There is one kind of reasoning by cases that it does not perform.

5/ The Knowledge Language of NeoClassic

Individuals in a NeoClassic knowledge base are either host individuals or classic individuals. Host individuals come from C++ and can be either integers, floats, or strings. Classic individuals are created by NeoClassic and represent anything desired.

Descriptions in NeoClassic are likewise either host descriptions or classic descriptions. As expected, host individuals can only satisfy host descriptions and classic individuals can only satisfy classic descriptions. Most descriptions exist in a particular knowledge base, and cannot refer to descriptions from other knowledge bases. Similarly, concepts, individuals, and rules must use descriptions that are valid for their knowledge base. The details of descriptions are contained elsewhere.

6/ The Collection of Knowledge Bases

NeoClassic maintains a collection of named knowledge bases. One of these knowledge bases is the current knowledge base. This knowledge base is used in the character interface and when looking up symbols.

The operations on the collection of knowledge bases are:

7/ Incoherency and Inconsistency Reporting in NeoClassic

If an operation in NeoClassic would result in an inconsistent knowledge base that operation is not performed. Instead the operation returns a special value, which encodes the relevant portion of the knowledge base and can be used to find and explain the source of the potential inconsistency. This result can be used to explain why the operation would have resulted in an inconsistent knowledge base.

Similarly, if an operation in NeoClassic would result in the creation of an incoherent concept, that concept is not added to the knowledge base. Instead the operation returns a special value, which can be used to find and explain the source of the potential incoherency.

8/ Explanation Facilities in NeoClassic

NeoClassic can explain anything that is has inferred about any concept or individual. It can explain why one description does/does not subsume another, why an individual does/does not satisfy a description, why a particular fact is/is not known about an individual or concept, and why a rule did/did not fire. NeoClassic can even explain the inferences that would have resulted in an inconsistent knowledge base.

Explanations report only the last (important) inference made in any chain of inferences. To see an entire chain of inferences a series of explanations must be requested, manually or automatically. There will eventually be mechanisms for controlling what is and what is not important.

9/ Hooks in NeoClassic

NeoClassic provides a facility that allows functions from outside NeoClassic to be run in response to particular activities performed by NeoClassic. These activities include the creation of roles, concepts, rules, and individuals; the addition of information to or the retraction of information from an individual; the firing of rules; the transfer of information from one individual to another; and the discovery of a new individual that satisfies a concept. This facility can be used to build user interfaces that maintain an up-to-date view of a NeoClassic knowledge base.

10/ Features to be Added in the Future

NeoClassic Conceptual Building Blocks

NeoClassic is a sophisticated knowledge representation system that allows close program direct but safe access to its data structures. To effectively access these data structures from a program requires a knowledge of how they are organized.

1/ NeoPtrObject and named objects

Many NeoClassic objects belong to the NeoPtrObject class. This class is actually a class of smart pointers that implement automatic storage management, currently be means of reference counting. There are type-checking operations provided for each subclass of NeoPtrObject to allow discrimination between the various subclasses of NeoPtrObject. There are also conditional downcasting operations provided for each subclass of NeoPtrObject.

The classes Role, Concept, Rule, and ClassicIndividual share functionality having to do with their similar position in knowledge bases. They each have a name and a knowledge base they belong to. They also have two kinds of modifiable data, a comment string and an arbitrary piece of information, that are not managed by NeoClassic. This common functionality is provided by a mechanism that is not visible to the user.

2/ Knowledge Bases

A knowledge base in NeoClassic contains a collection of consistent information. This information is stored in the form of roles, concepts, rules, and classic individuals. Each knowledge base also has a name.

When a knowledge base is created, it contains only the definitions of the built in NeoClassic concepts. These are:

A knowledge base continually computes the consequences of all information it contains. Any operation that would result in an inconsistent knowledge base is rejected. Part of this information is a classification and instantiation taxonomy of concepts and classic individuals.

The roles, concepts, rules, and classic individuals in a knowledge base can be retrieved by name.

3/ The Knowledge Base Collection

NeoClassic also maintains a collection of named knowledge bases. In the normal course of events every knowledge base is in this collection of knowledge bases. There are operations to add a named knowledge base to this collection, to remove a knowledge base from this collection, and to find a knowledge base in this collection given a name. One of the knowledge bases in this collection is the current knowledge base. There are operations to return the current knowledge base and to make a knowledge base be the current knowledge base. The current knowledge base is used in several operations, including when coercing a symbol to a role, concept, rule, or classic individual.

There are also operations to initialize the collection of knowledge bases, to reinitialize it, and clean it up by destroying all the knowledge bases in the collection. The newly initialized or reinitialized collection contains a single fresh knowledge base, which is the current knowledge base.

4/ Descriptions

A description in NeoClassic is a formal object that represents a collection of the objects of a model or interpretation. Objects that are in the collection are said to satisfy the description. A description is said to subsume another description if for every model the collection it represents is a superset of the collection the other description represents. A description is said to be incoherent if the collection it represents is empty in all models.

NeoClassic divides descriptions into concepts and constructed descriptions. Concepts are defined in a particular knowledge base in terms of a description and primitive information. Constructed descriptions are formed by one of the description constructors.

NeoClassic also divides descriptions into thing descriptions, classic descriptions, host descriptions, and incoherent descriptions. The collection of objects represented by a classic description must come only from the classic objects of the model, and the collection of objects represented by a host description must come only from the host objects of the model. The host objects of a model are strings, integers, and floats. The classic objects of a model are all the other objects in the model. Thing descriptions represent the union of all classic objects and host objects; incoherent descriptions structurally represent the empty set. (Note that it is possible to have classic descriptions and host descriptions that represent the empty set.)

5/ Roles

A role in NeoClassic is a formal object that represents a relation from the classic domain of a model to the entire domain. Roles are created in knowledge bases. Roles can be tagged as attributes, i.e., a role whose relation is a (partial) function.

Currently roles are atomic entities, but a role hierarchy will be added in a future release.

6/ Concepts

A concept in NeoClassic is a formal object that represents a collection of objects of a model. Concepts are defined in a knowledge base. Concepts are divided into thing concepts, whose definition is a thing description; classic concepts, whose definition is a classic description plus some primitive information; and host concepts, whose definition is a host description. Definitions of concepts must refer only to concepts that have already been defined in the knowledge base.

The representation of a host concept is precisely the representation of its definition. The representation of a classic concept is a subset of the representation of the description in its definition. If the classic concept is not primitive then its representation is precisely the representation of this description. If it is primitive then the representation must also be disjoint from selected other primitive concepts.

7/ Rules

A rule in NeoClassic is a formal object that represents a mapping between the representation of its antecedent and the representation of its consequent. A rule requires that all classic individuals in the knowledge base that belong to its antecedent also belong to its consequent. Rules are created in knowledge bases.

The consequent of a rule can be specified as a description, as a function from classic individuals to descriptions, or as a function from classic individuals and roles to sets of individuals. In the first case the consequent of the rule is the description provided, in the second case it is the description returned when the function is run, and in the third case the description is a fills description created from the role and the set of individuals.

8/ Individuals

Individuals in NeoClassic are either Classic Individuals or Host Individuals.

A classic individual is a formal object that represents a classic object in a model. Classic Individuals are created in knowledge bases, and information can be added to them and removed from them. This information is either in the form of a description or a role closing. Adding a description means that the classic individual is required to satisfy the description. Adding a role closing means that the only fillers for the role on the individual are the ones currently known.

Classic Individuals that belong to a knowledge base must be consistent, as knowledge bases are consistent. However, operations that would have resulted in an inconsistent knowledge base return inconsistent individuals to encode the inconsistent relevant state that would have resulted if the operation was performed.

A host individual is both a formal object that represents a host object in a model and a data structure in C++. Host individuals are thus either strings, integers, or reals. They exist in all knowledge bases and, of course, cannot be changed.

NeoClassic Interface Functionality

NeoClassic currently provides three low-level interfaces, a character-based interface (CI), a graphical user interface (GUI), and a C++ application program interface (API). All three interfaces can exercise the full knowledge representation capabilities of NeoClassic. This document includes information on all the user-callable NeoClassic functions, giving both their C++ signature and their syntax in the character interface.

In the character interface commands are given to NeoClassic over a character stream, and responses are given back on another character stream. Many character interface functions accept a set as a last argument. This can either be entered as a sequence of arguments, each of which become an element of the set, like

(fills role ind1 ind2 ind3 ind4)
or as a single argument, which becomes the set itself, like
(fills role (getInstances C))
In the descriptions below, functions like this are written as follows
(fills role ClassicIndividual...)

The C++ application programming interface to NeoClassic exposes the object-oriented implementation of NeoClassic, but in a way that does not (easily) allow subverting the semantics of NeoClassic objects. There is some functionality that only makes sense using the application programming interface and thus does not show up in the character interface, and vice versa.

Many of the character interface function names are provided solely for compatability with C-Classic. Such names are marked with ``©''. A few character interface function names are provided as shorthand, and should not be used except when typing directly into the character interface. Such function names are marked with ``£''.

The application programming interface does not print error messages. Exceptional conditions are signalled through return values. Some functions return null objects, which indicate some sort of non-knowledge exceptional condition, such as trying to create a concept when the name is already in use for another concept in the knowledge base. Knowledge exceptional conditions are those that would result in an illegal state of affairs in a knowledge base (including creating an incoherent concept in the knowledge base, making the knowledge base inconsistent, etc.) are signalled by returning an incoherent or inconsistent object. Exceptional return values are prominently indicated below. Note that passing a null object into another function may generate abnormal behavior, including dumping core.

The character interface does print messages. In particular it checks for exceptional returns and prints a message explaining the exceptional return. The character interface also does not continue evaluating a form if a sub-form produced a null object.

1/ Interface-Visible Classes Provided or Used by NeoClassic

NeoClassic provides or uses a number of C++ classes that are visible in the two interfaces. In the following list of classes
Sub : Super...
means Sub is a child class of each of the Supers.

Most of the C++ classes provided by NeoClassic are organized under the class NeoPtrObject.

	NeoPtrObject
	KnowledgeBase :		NeoPtrObject
	Description :		NeoPtrObject
	ThingDescription:	Description
	ClassicDescription :	Description
	HostDescription :	Description
	Construct :		Description
	ThingConstruct:		Construct, ThingDescription
	ClassicConstruct :	Construct, ClassicDescription
	HostConstruct :		Construct, HostDescription
	IncoherentConstruct :	Construct
	Role :			NeoPtrObject
	Concept :		Description
	ThingConcept :		Concept, ThingDescription
	ClassicConcept :	Concept, ClassicDescription
	HostConcept :		Concept, HostDescription
	Rule :			NeoPtrObject
	ClassicIndividual :	NeoPtrObject
The following C++ classes or enumerations provided or used by NeoClassic are not (seen to be) subclasses of NeoPtrObject.
	String
	Symbol
	Boolean 	{ false, true }
	HostType 	{ negativeInfinity, positiveInfinity,
			  integerType, floatType, stringType }
	TestVal		{ testFalse, testMaybe, testTrue }
	KBSymbol

	NeoSet<T>
	IndividualSet
	ClassicOneOf
	HostOneOf

	MinOrMax
	HostIndividual
	IntOrFloat

	Primitive

	RuleConsequent
	ClassicDescriptionConsequent : RuleConsequent
	ComputedDescription : RuleConsequent
	ComputedFillers : RuleConsequent

	ClassicTestGenerate
	HostTestGenerate
	ComputedDescriptionGenerate
	ComputedFillersGenerate

	ClassicTestDetail
	HostTestDetail
	ComputedDescriptionDetail
	ComputedFillersDetail

	ClassicTest
	HostTest

	NeoObject
Descriptions of some of the classes above are given here. Descriptions of the other classes are given later in this document.
class NeoPtrObject

The class NeoPtrObject forms the root of a hierarchy of classes that are made visible by NeoClassic. It is a ``smart pointer'' class with reference counting. Therefore all subclasses of NeoPtrObject act as smart pointers, so copies of an object under NeoPtrObject refer to the same data structure and the storage used is reclaimed when the last reference to it goes away. NeoPtrObjects can be compared, just like regular pointers.

There are ``null objects'' possible under NeoPtrObject, i.e., objects that do not point to any data. A null object can be checked for in the usual way (by comparison with 0). Functions that can return such null objects are prominently indicated.

Boolean NeoPtrObject::isCLASS() const
(isCLASS NeoPtrObject) -> Boolean

For each subclass CLASS of NeoPtrObject there is a Boolean function that determines whether an object actually is (points to) an instance of that class.

CLASS NeoPtrObject::DCAST(CLASS) const

Because NeoPtrObject is a smart pointer class, the type of the actual data structure may be more specific than the declared type of the object. For each subclass CLASS of NeoPtrObject there is a conditional ``downcasting'' function that coerces an object of type NeoPtrObject to an object of (pointer to) the subclass.

[NULL return] If the object does not actually belong to the subclass, a null object is returned.

class String
class Symbol

These classes provide support for strings of characters and objects whose value is a string but that can be quickly compared for equality. Their interface is compatible with the standard components library.

enum Boolean { false, true }

A type for boolean values.

enum TestVal {testFalse, testMaybe, testTrue}

The values that are returned by test functions.

enum HostType { negativeInfinity=-2, positiveInfinity=-1, integerType, floatType, stringType }

An enumeration of the types of host individuals.

template<class T> class NeoSet<T>

The template class NeoSet implements reference-counted sets. Its interface is compatible with interface for sets in the standard components library.

class IndividualSet

An individual set is a set consisting of either classic or host individuals. It supports all reasonable set operations.

class ClassicOneOf
class HostOneOf

A classic one-of and a host one-of are sets of classic or host (respectively) individuals that can also be a universal set. They support all reasonable set operations.

Boolean ClassicOneOf::universe() const
Boolean HostOneOf::universe() const

Determine whether a one-of is a universal set.

NeoSet<ClassicIndividual> ClassicOneOf::getElements() const
NeoSet<HostIndividual> HostOneOf::getElements() const

Return the elements of the one-of, unless it is a universal set, in which case an empty set is returned.

class RuleConsequent
class ClassicDescriptionConsequent : public RuleConsequent
class ComputedDescription : public RuleConsequent
class ComputedFillers : public RuleConsequent

These classes hold the consequent of a rule.

class ClassicTestGenerate
class HostTestGenerate
class ComputedDescriptionGenerate
class ComputedFillersGenerate
class ClassicTestDetail
class HostTestDetail
class ComputedDescriptionDetail
class ComputedFillersDetail
class ClassicTest
class HostTest

These classes implement user functions.

class NeoObject

NeoObject is a discriminated union of several different kinds of information, currently including int, float, String, Symbol, Boolean, IndividualSet, Primitive, NeoPtrObject, and a list of NeoObjects. There are conversion operators to and from NeoObject for each of these and also for the subclasses of NeoPtrObject. NeoSet<Symbol> -> Primitive
NeoClassic provides conditional coercion of String, Symbol, and char* into Role, Concept, ClassicConcept, HostConcept, Rule, and ClassicIndividual by look-up in the current knowledge base. If there is no object of the correct type in the current knowledge base, a null object is returned.

In the Character Interface, more-general classes are conditionally coerced into more-specific classes. For example, if a function requires a ClassicDescription, but its argument produces a Description, the Character Interface will check to see if the result of evaluating the argument is actually a ClassicDescription, and will use it if so. If the result is not a ClassicDescription, the Character Interface will report an error.

In the Character Interface, Symbols can be coerced into ClassicTestGenerate, HostTestGenerate, ComputedDescriptionGenerate, and ComputedFillersGenerate by looking the symbol up in tables. These tables are populated as a side-effect of creating objects in ClassicTestGenerate, HostTestGenerate, ComputedDescriptionGenerate, and ComputedFillersGenerate.

2/ Knowledge Bases

class KnowledgeBase : public NeoPtrObject

A knowledge base is a collection of information that is managed by NeoClassic. The logic operations of NeoClassic are performed on knowledge bases or on the major components of knowledge bases.

Every knowledge base starts out with several pre-defined concepts.

    Concept Name	Definition

    Thing		Description::and()
    ClassicThing	Description::and(NeoSet<ClassicDescription>())
    HostThing		Description::and(NeoSet<HostDescription>())
    Number 		Description::testH(numberp)
    Integer		Description::and(Number,testH(integerp))
    Float		Description::and(Number,testH(floatp))
    String		Description::testH(stringp)

a) Managing the Collection of Knowledge Bases

There is a single collection of all knowledge bases, maintained as a map from symbols to knowledge bases. There is also a current knowledge base, which is one of the knowledge bases in this collection. The collection of knowledge bases is initialized to contain a single knowledge base, which is the current knowledge base, when NeoEnvironment::init is called.

Knowledge bases only really exist as members of this collection. Whenever a knowledge base is removed from the collection, all information is removed from it. The knowledge base should not be modified or accessed thereafter.

static void KnowledgeBase::reinitCollection()
(reinitCollection)
(reset)©

Remove all knowledge bases from the collection of knowledge bases and then intialize as during NeoEnvironment::init.

static KnowledgeBase KnowledgeBase::getCurrent()
(getCurrentKnowledgeBase) -> KnowledgeBase
(getCurrent) -> KnowledgeBase

Return the current knowledge base.

[NULL return] If there is no current knowledge base, return a null knowledge base.

static KnowledgeBase KnowledgeBase::setCurrent(const Symbol&)
(setCurrentKnowledgeBase Symbol) -> KnowledgeBase
(setCurrent Symbol) -> KnowledgeBase

Set the current knowledge base to the one with the given name and return it.

[NULL return] If there is no knowledge base with this name, then don't change the current knowledge base and return a null knowledge base.

static KnowledgeBase KnowledgeBase::setCurrent(KnowledgeBase)
(setCurrentKnowledgeBase KnowledgeBase) -> KnowledgeBase
(setCurrent KnowledgeBase) -> KnowledgeBase

Set the current knowledge base and return it.

[NULL return] If the argument is null, then don't change the current knowledge base and return a null knowledge base.

static KnowledgeBase KnowledgeBase::create(const Symbol &)
(createKnowledgeBase Symbol) -> KnowledgeBase

Create and return a new knowledge base with a given name. If the name is an empty string, generate a new name for the knowledge base.

[NULL return] If a knowledge base with that name already exists, then return a null knowledge base.

static KnowledgeBase KnowledgeBase::find (const Symbol&)
(findKnowledgeBase Symbol) -> KnowledgeBase

Find the knowledge base with a given name in the collection of knowledge bases. If the name is an empty string, return the current knowledge base instead.

[NULL return] If there is no knowledge base with the name, return a null knowledge base.

static Boolean KnowledgeBase::remove(const Symbol&)
(removeKnowledgeBase Symbol) -> Boolean

Remove the knowledge base with a given name from the collection of knowledge bases. If there is no such knowledge base, return false. If the current knowledge base is deleted, set the current knowledge base to another knowledge base.

It is impossible to make the knowledge base collection empty with this function, as another knowledge base will be created in this case.

static Boolean KnowledgeBase::remove(KnowledgeBase)
(removeKnowledgeBase KnowledgeBase) -> Boolean

Remove the given knowledge base from the collection of knowledge bases. If the knowledge base is null, return false. If the current knowledge base is deleted, set the current knowledge base to another knowledge base.

It is impossible to make the knowledge base collection empty with this function, as another knowledge base will be created in this case.

Symbol KnowledgeBase::getName() const
(getName KnowledgeBase) -> Symbol
(getName) -> Symbol

Return the name of a knowlege base. The argumentless version of the function in the character interface returns the name of the current knowledge base.

b) Retrieving built-in concepts

The built-in concepts can be retrieved using these functions. They can also be retrieved by name.
ThingConcept KnowledgeBase::thing() const
ClassicConcept KnowledgeBase::classicThing() const
HostConcept KnowledgeBase::hostThing() const
HostConcept KnowledgeBase::numberConcept() const
HostConcept KnowledgeBase::integerConcept() const
HostConcept KnowledgeBase::floatConcept() const
HostConcept KnowledgeBase::stringConcept() const

c) Retrieving Information by Name

The information in a knowledge base is maintained in maps from symbols to several different kinds of information. There is one map for roles, one for concepts, one for rules, and one for classic individuals.

Role KnowledgeBase::symbolToRole(const Symbol&)
(symbolToRole Symbol) -> Role
(role Symbol) -> Role©

Return the role in the knowledge base with a particular name.
The character interface versions uses the current knowledge base.

[NULL return] If there is no such role, return a null role.

Concept KnowledgeBase::symbolToConcept(const Symbol&)
(symbolToConcept Symbol) -> Concept
(concept Symbol) -> Concept©

Return the concept in the knowledge base with a particular name.
The character interface versions use the current knowledge base.

[NULL return] If there is no such concept, return a null concept.

Concept KnowledgeBase::symbolToClassicConcept(const Symbol&)
(symbolToClassicConcept Symbol) -> ClassicConcept
(classic-concept Symbol) -> ClassicConcept©

Return the classic concept in the knowledge base with a particular name.
The character interface versions use the current knowledge base.

[NULL return] If there is no such classic concept, return a null classic concept.

Concept KnowledgeBase::symbolToHostConcept(const Symbol&)
(symbolToHostConcept Symbol) -> HostConcept
(host-concept Symbol) -> HostConcept©

Return the host concept in the knowledge base with a particular name.
The character interface versions use the current knowledge base.

[NULL return] If there is no such host concept, return a null host concept.

Rule KnowledgeBase::symbolToRule(const Symbol&)
(symbolToRule Symbol) -> Rule
(rule Symbol) -> Rule

Return the rule in the knowledge base with a particular name.
The character interface versions use the current knowledge base.

[NULL return] If there is no such rule, return a null rule.

ClassicIndividual KnowledgeBase::symbolToClassicIndividual(const Symbol&)
(symbolToClassicIndividual Symbol) -> ClassicIndividual
(classic-individual Symbol) -> ClassicIndividual©

Return the classic individual in the knowledge base with a particular name.
The character interface versions use the current knowledge base.

[NULL return] If there is no such classic individual, return a null classic individual.

d) Creating Objects in a Knowledge Base

One way to add information to a knowledge base is to add a new role, concept, rule, or classic individual to the knowledge base.

Role KnowledgeBase::createRole(const Symbol & name, const Boolean & attribute = false)
(createRole Symbol [Boolean]) -> Role
(define-role Symbol) -> Role©
(define-attribute Symbol) -> Role©

Add a new role with a given name to the knowledge base. If the name is the empty string, generate a new name for the role. If attribute is true, the role will be an attribute, i.e., any object can have at most one filler for it. The character interface function use the current knowledge base. The define-attribute version sets the attribute argument to true.

[NULL return] If there already is a role with that name, return a null role.

ClassicConcept KnowledgeBase::createConcept(const Symbol& name,
const ClassicDescription& defntn, const Primitive & primitive=false)
ClassicConcept KnowledgeBase::createConcept(const Symbol& name,
const ClassicDescription& defntn, const Boolean & primitive)
ClassicConcept KnowledgeBase::createConcept(const Symbol & name,
const ClassicDescription& defntn, const NeoSet<Symbol> & primitive)
(createConcept Symbol ClassicDescription [Boolean]) -> ClassicConcept
(createConcept Symbol ClassicDescription Symbol...) -> ClassicConcept
(define-concept Symbol ClassicDescription) -> ClassicConcept©
(define-primitive Symbol ClassicDescription) -> ClassicConcept©
(define-disjoint-primitive Symbol ClassicDescription Symbol...) -> ClassicConcept©

Add a new classic concept with a given name, given definition, and given primitive information to the knowledge base. If the primitive information is not specified, create a defined concept. If the name is the empty string, generate a new name for the concept.
The character interface versions use the current knowledge base. The define-primitive version sets the primitive argument to true.

[NULL return] If there already is a concept with that name, return a null classic concept.

[INCOHERENT return] If the concept is incoherent, do not add it to the knowledge base.

HostConcept KnowledgeBase::createConcept(const Symbol & name, const HostDescription& definition)
(createConcept Symbol HostDescription) -> HostConcept
(define-concept Symbol HostDescription) -> HostConcept©

Add a new host concept with a given name and given definition to the knowledge base. If the name is the empty string, generate a new name for the concept.
The character interface versions use the current knowledge base.

[NULL return] If there already is a concept with that name, return a null host concept.

[INCOHERENT return] If the concept is incoherent, do not add it to the knowledge base.

Rule KnowledgeBase::createRule(const Symbol& name, const ClassicConcept& antecedent,
const ClassicDescription& consequent)
Rule KnowledgeBase::createRule(const Symbol& name, const ClassicConcept& antecedent,
const RuleConsequent& consequent)
(createRule Symbol ClassicConcept ClassicDescription) -> Rule
(define-rule Symbol ClassicConcept ClassicDescription) -> Rule©
(createRule Symbol ClassicConcept RuleConsequent) -> Rule
(define-rule Symbol ClassicConcept RuleConsequent) -> Rule©

Add a new rule with a given name and given antecedent and consequent to the knowledge base. If the name is the empty string, generate a new name for the rule. Run the rule on all instances of the antecedent.
The character interface versions use the current knowledge base.

[NULL return] If there already is a rule with that name, return a null rule.

[INCONSISTENT return] If running the rule on instances of the antecedent results in an inconsistent knowledge base, do not change the knowledge base. In this case return an inconsistent rule that contains the relevant state of the knowledge base that would have resulted if the rule had been added.

ClassicIndividual KnowledgeBase::createIndividual(const Symbol& name)
ClassicIndividual KnowledgeBase::createIndividual(const Symbol& name, const ClassicDescription&)
(createIndividual Symbol) -> ClassicIndividual
(define-individual Symbol) -> ClassicIndividual©
(createIndividual Symbol ClassicDescription) -> ClassicIndividual
(define-individual Symbol ClassicDescription) -> ClassicIndividual©

Add a new classic individual with a given name and given definition to the knowledge base. If the name is the empty string, generate a new name for the classic individual. If no definition is provided, use ClassicThing.
The character interface versions use the current knowledge base.

[NULL return] If there already is a classic individual with that name, return a null classic individual.

[INCONSISTENT return] If adding the classic individual makes the knowledge base inconsistent, do not change the knowledge base. In this case return an inconsistent classic individual that contains the relevant state of the knowledge base that would have resulted if the classic individual had been added.

e) Writing a Knowledge Base to a file

void KnowledgeBase::write(ostream &os) const
(writeKnowledgeBase String)
(writeKnowledgeBase KnowledgeBase String)

Write the information in the current or specified Knowledge Base to a stream or to the file with the given name. The file can be read using loadFile, but should NOT be modified as it may contain some internal NeoClassic function calls that can produce corrupted knowledge bases if not used correctly.

3/ Descriptions

class Description : public NeoPtrObject

Descriptions encode most of the actual information in NeoClassic. Descriptions are divided into subclasses in several ways.

a) Subclasses of Descriptions

First, descriptions are divided into realms, that is those descriptions that can describe any object in a domain, those descriptions that can only describe the classic objects in a domain, and those descriptions that can only describe the host objects in a domain.

class ThingDescription: public virtual Description
class ClassicDescription : public virtual Description
class HostDescription : public virtual Description

Second, descriptions are divided between concepts, that is named descriptions in a knowledge base; and constructs, that is constructed descriptions. The distinction between concepts and constructs is not very important, and Construct is only mentioned because some functions return Constructs. User code should just cast these Constructs into Descriptions.

class Construct : public virtual Description
class Concept : public virtual Description

Constructs and Concepts are likewise both divided into realms.

class ThingConstruct : public Construct, ThingDescription
class ClassicConstruct : public Construct, ClassicDescription
class HostConstruct : public Construct, HostDescription
class IncoherentConstruct : public Construct
class ThingConcept : public Concept, ThingDescription
class ClassicConcept : public Concept, ClassicDescription
class HostConcept : public Concept, HostDescription

b) Creating Constructed Descriptions

Constructed Descriptions (Constructs) are created by means of various functions, one for each of the constructors defined in the description logic underlying NeoClassic.

static ThingDescription Description::and()
(and) -> ThingDescription

static Description Description::and(const NeoSet<Description>&)
(and Description...) -> Description

These two constructors can also return a Concept, so their return type is Description.

static Construct Description::oneOf(const IndividualSet&)
(oneOf) -> Construct
(one-of) -> Construct©

static ClassicDescription Description::and(const NeoSet<ClassicDescription>&)

static ClassicConstruct Description::oneOf(const NeoSet<ClassicIndividual>&)
(oneOf ClassicIndividual...) -> ClassicConstruct
(one-of ClassicIndividual...) -> ClassicConstruct©
(oneOf Symbol...) -> ClassicConstruct
(one-of Symbol...) -> ClassicConstruct©

static ClassicConstruct Description::atLeast(unsigned int min, const Role&)
(atLeast unsigned_int Role) -> ClassicConstruct
(at-least unsigned_int Role) -> ClassicConstruct©

static ClassicConstruct Description::atMost(unsigned int max, const Role&)
(atMost unsigned_int Role) -> ClassicConstruct
(at-most unsigned_int Role) -> ClassicConstruct©

static ClassicConstruct Description::fills(const Role&,const IndividualSet&)
(fills Role ClassicIndividual...) -> ClassicConstruct
(fills Role Symbol...) -> ClassicConstruct
(fills Role HostIndividual...) -> ClassicConstruct

static ClassicConstruct Description::all(const Role&, const Description&)
(all Role Description) -> ClassicConstruct

static ClassicConstruct Description::testC(const ClassicTestGenerate * prot,
const List<NeoObject>& parameters = List<NeoObject>())
(testC ClassicTestGenerate [NeoObject...]) -> ClassicConstruct
(test-c ClassicTestGenerate [NeoObject...]) -> ClassicConstruct©

static HostDescription Description::and(const NeoSet<HostDescription>&)

static HostConstruct Description::oneOf(const NeoSet<HostIndividual>&)
(oneOf HostIndividual...) -> HostConstruct
(one-of HostIndividual...) -> HostConstruct©

static HostConstruct Description::minimum(const IntOrFloat& min)
(minimum IntOrFloat) -> HostConstruct
(lower-limit IntOrFloat) -> HostConstruct©

static HostConstruct Description::maximum(const IntOrFloat& max)
(maximum IntOrFloat) -> HostConstruct
(upper-limit IntOrFloat) -> HostConstruct©

static HostConstruct Description::testH(const HostTestGenerate * proto,
const List<NeoObject>& parameters = List<NeoObject>())
(testH HostTestGenerate [NeoObject...]) -> ClassicConstruct
(test-h HostTestGenerate [NeoObject...]) -> ClassicConstruct©

c) Queries

Boolean Description::incoherent() const
(incoherent Description) -> Boolean

Determine whether a description is incoherent.

Boolean Description::subsumes(const Description&) const
(subsumes Description Description) -> Boolean
(subsumes? Description Description) -> Boolean©

Boolean Description::subsumes(const ClassicIndividual&) const
(subsumes Description ClassicIndividual) -> Boolean
(subsumes? Description ClassicIndividual) -> Boolean©

Boolean Description::subsumes(const HostIndividual&) const
(subsumes Description HostIndividual) -> Boolean
(subsumes? Description HostIndividual) -> Boolean©

Determine whether one description subsumes another, or a classic or host individual.

d) Told Retrievals

The following functions retrieve various information that was TOLD about the description. In several cases there are two versions of a function, one that returns a set of the told information and one that returns this told information combined into one piece.
NeoSet<ClassicConcept> ClassicDescription::toldParents() const
(toldParents ClassicDescription) -> NeoSet<ClassicConcept>
(concept-told-parents ClassicDescription) -> NeoSet<ClassicConcept©

NeoSet<unsigned int> ClassicDescription::toldAtLeasts(const Role&) const
(toldAtLeasts ClassicDescription Role) -> NeoSet<unsigned int>

unsigned int ClassicDescription::toldAtLeast(const Role &) const
(toldAtLeast ClassicDescription Role) -> unsigned int

NeoSet<unsigned int> ClassicDescription::toldAtMosts(const Role&) const
(toldAtMosts ClassicDescription Role) -> NeoSet<unsigned int>

unsigned int ClassicDescription::toldAtMost(const Role&) const
(toldAtMost ClassicDescription Role) -> unsigned int

IndividualSet ClassicDescription::toldFillers(const Role&) const
(toldFillers ClassicDescription Role) -> IndividualSet

NeoSet<Description> ClassicDescription::toldValueDescriptions(const Role&) const
(toldValueDescriptions ClassicDescription Role)-> NeoSet<Description>

Description ClassicDescription::toldValueDescription(const Role &) const
(toldValueDescription ClassicDescription Role) -> Description

NeoSet<NeoSet<ClassicIndividual>> ClassicDescription::toldOneOfs() const
(toldOneOfs ClassicDescription) -> NeoSet<NeoSet<ClassicIndividual>>

ClassicOneOf ClassicDescription::toldOneOf() const
(toldOneOf ClassicDescription) -> ClassicOneOf
(concept-told-one-of ClassicDescription) -> ClassicOneOf©

NeoSet<ClassicTest> ClassicDescription::toldTests() const
(toldTests ClassicDescription) -> NeoSet<ClassicTest>
(concept-told-tests ClassicDescription) -> NeoSet<ClassicTest>©

NeoSet<HostConcept> HostDescription::toldParents() const
(toldParents HostDescription) -> NeoSet<HostConcept>
(concept-told-parents HostDescription) -> NeoSet<HostConcept>©

NeoSet<NeoSet<HostIndividual>> HostDescription::toldOneOfs() const
(toldOneOfs HostDescription) -> NeoSet<NeoSet<HostIndividual>>

HostOneOf HostDescription::toldOneOf() const
(toldOneOf HostDescription) -> HostOneOf
(concept-told-one-of HostDescription) -> HostOneOf©

NeoSet<IntOrFloat> HostDescription::toldMinimums() const
(toldMinimums HostDescription) -> NeoSet<IntOrFloat>

MinOrMax HostDescription::toldMinimum() const
(toldMinimum HostDescription) -> MinOrMax

NeoSet<IntOrFloat> HostDescription::toldMaximums() const
(toldMaximums HostDescription) -> NeoSet<IntOrFloat>

MinOrMax HostDescription::toldMaximum() const
(toldMaximum HostDescription) -> MinOrMax

NeoSet<HostTest> HostDescription::toldTests() const
(toldTests HostDescription) -> NeoSet<HostTest>
(concept-told-tests HostDescription) -> NeoSet<HostTest>©

e) Derived Retrievals

The following functions retrieve various information that was DERIVED about the description, that is a combination of the told information plus any information that could be inferred.

NeoSet<ClassicConcept> ClassicDescription::derivedPrimitives() const
(derivedPrimitives ClassicDescription) -> NeoSet<ClassicConcept>

unsigned int ClassicDescription::derivedAtLeast(const Role &) const
(derivedAtLeast ClassicDescription Role) -> unsigned int
(concept-role-description-min ClassicDescription Role) -> unsigned int©

unsigned int ClassicDescription::derivedAtMost(const Role &) const
(derivedAtMost ClassicDescription Role) -> unsigned int
(concept-role-description-max ClassicDescription Role) -> unsigned int©

IndividualSet ClassicDescription::derivedFillers(const Role &) const
(derivedFillers ClassicDescription Role) -> IndividualSet
(concept-role-fillers ClassicDescription Role) -> IndividualSet©

Description ClassicDescription::derivedValueDescription(const Role &) const
(derivedValueDescription ClassicDescription Role) -> Description
(concept-role-description-value ClassicDescription Role) -> Description©

ClassicOneOf ClassicDescription::derivedOneOf() const
(derivedOneOf ClassicDescription) -> ClassicOneOf
(concept-one-of ClassicDescription) -> ClassicOneOf©

NeoSet<ClassicTest> ClassicDescription::derivedTests() const
(derivedTests ClassicDescription) -> NeoSet<ClassicTest>
(concept-tests ClassicDescription) -> NeoSet<ClassicTest>©

Boolean ClassicDescription::derivedFullRole() const
(derivedFullRole ClassicDescription Role) -> Boolean

A role is full on an individual or concept if it has as many fillers on the role as its atMost description on the role. Note that this is different from the role being closed. (A closed role is full, but a role may be full without having been closed.)

HostOneOf HostDescription::derivedOneOf() const
(derivedOneOf HostDescription) -> HostOneOf
(concept-one-of HostDescription) -> HostOneOf©

MinOrMax HostDescription::derivedMinimum() const
(derivedMinimum HostDescription) -> MinOrMax

MinOrMax HostDescription::derivedMaximum() const
(derivedMaximum HostDescription) -> MinOrMax

NeoSet<HostTest> HostDescription::derivedTests() const
(derivedTests HostDescription) -> NeoSet<HostTest>
(concept-tests HostDescription) -> NeoSet<HostTest>©

4/ Named Objects

The classes Role, Concept, Rule, and ClassicIndividual share functionality having to do with their position in a knowledge base. For various reasons there is no C++ class for named objects.
Role::Role(const Symbol & name)
Role::Role(const String & name)
Role::Role(const char* name)
Concept::Concept(const Symbol & name)
Concept::Concept(const String & name)
Concept::Concept(const char* name)
ClassicConcept::ClassicConcept(const Symbol & name)
ClassicConcept::ClassicConcept(const String & name)
ClassicConcept::ClassicConcept(const char* name)
HostConcept::HostConcept(const Symbol & name)
HostConcept::HostConcept(const String & name)
HostConcept::HostConcept(const char* name)
Rule::Rule(const Symbol & name)
Rule::Rule(const String & name)
Rule::Rule(const char* name)
ClassicIndividual::ClassicIndividual(const Symbol & name)
ClassicIndividual::ClassicIndividual(const String & name)
ClassicIndividual::ClassicIndividual(const char* name)

Return the role, concept, classic concept, host concept, rule, or classic individual with the given name in the current knowledge base.

[NULL return] If such a role, concept, classic concept, host concept, rule, or classic individual does not exist; return a null role, concept, classic concept, host concept, rule, or classic individual, as appropriate.

KnowledgeBase Role::getKnowledgeBase() const
(getKnowledgeBase Role) -> KnowledgeBase
(getKB Role) -> KnowledgeBase £

KnowledgeBase Concept::getKnowledgeBase() const
(getKnowledgeBase Concept) -> KnowledgeBase
(getKB Concept) -> KnowledgeBase £

KnowledgeBase Rule::getKnowledgeBase() const
(getKnowledgeBase Rule) -> KnowledgeBase
(getKB Rule) -> KnowledgeBase £

KnowledgeBase ClassicIndividual::getKnowledgeBase() const
(getKnowledgeBase ClassicIndividual) -> KnowledgeBase
(getKB ClassicIndividual) -> KnowledgeBase £

Return the knowledge base that the object belongs to.

[NULL return] If the object does not belong to a knowledge base, a null knowledge base is returned. This should only happen for incoherent or inconsistent objects or objects that have been ``destroyed'' by being removed from their knowledge base or by having their knowledge base destroyed.

Symbol Role::getName() const
(getName Role) -> Symbol

Symbol Concept::getName() const
(getName Concept) -> Symbol

Symbol Rule::getName() const
(getName Rule) -> Symbol

String ClassicIndividual::getName() const
(getName ClassicIndividual) -> Symbol

Return the name of the object.

void Role::setComment(String)
(setComment Role String)
(set-descriptor Role String)©

void Concept::setComment(String)
(setComment Concept String)
(set-descriptor Concept String)©

void Rule::setComment(String)
(setComment Rule String)
(set-descriptor Rule String)©

void ClassicIndividual::setComment(String)
(setComment ClassicIndividual String)
(set-descriptor ClassicIndividual String)©

Set the comment field of the object. The comment field is not used by NeoClassic.

String Role::getComment() const
(getComment Role) -> String
(descriptor Role) -> String©

String Concept::getComment() const
(getComment Concept) -> String
(descriptor Concept) -> String©

String Rule::getComment() const
(getComment Rule) -> String
(descriptor Rule) -> String©

String ClassicIndividual::getComment() const
(getComment ClassicIndividual) -> String
(descriptor ClassicIndividual) -> String©

Return the comment field of the object

void Role::setUserData(void *)
void Concept::setUserData(void *)
void Rule::setUserData(void *)
void ClassicIndividual::setUserData(void *)

Set the user-data field of the object. The user-data field is not used by NeoClassic.

void * Role::getUserData()
void * Concept::getUserData()
void * Rule::getUserData()
void * ClassicIndividual::getUserData()

Return the user-data field of the object

5/ Roles

class Role : public NeoPtrObject

A role represents a relationship from classic objects in a domain to objects in a domain.

Boolean Role::isAttribute() const
(isAttribute Role) -> Boolean
(attribute? Role) -> Boolean©

Return whether this role is an attribute.

6/ Concepts

class Concept : public Description
class ThingConcept : public Concept, ThingDescription
class ClassicConcept : public Concept, ClassicDescription
class HostConcept : public Concept, HostDescription

A concept represents a subset of a domain. As mentioned above, concepts are divided into realms. Thing concepts represent the entire domain; a classic concept represents a subset of the classic portion of a domain; a host concept represents a subset of the host portion of a domain.

a) Primitives

class Primitive

Primitives provide extra information when defining classic concepts. A defined or non-primitive classic concept represents precisely the representation of the description that is used to define it. A primitive classic concept represents some undefined subset of this description. A disjoint-primitive classic concept is further disjoint from all other disjoint-primitive classic concepts that mention any element of disjointness tags.

Primitive::Primitive()

Non-primitive.

Primitive::Primitive(Boolean)

Coerce a boolean into a primitive. True becomes primitive, false becomes defined or non-primitive.

Primitive::Primitive(NeoSet<Symbol> & disjoint)

Create a disjoint primitive with the given disjointness tags.

operator Primitive::Boolean() const

Return whether the primitive is really primitive.

const NeoSet<Symbol> & Primitive::getDisjoint() const

Return the set of disjointness tags.

b) Simple Retrievals

const Description& Concept::getDescription () const
(getDescription Concept) -> Description

Return the description that was used to define the concept.

Primitive Concept::getPrimitive() const
(getPrimitive Concept) -> Primitive

Return the primitive information that was used to define the concept. Host concepts are, by definition, never primitive, so the equivalent of ``not primitive'' is returned for them.

Boolean Concept::isPrimitive() const
(isPrimitive Concept) -> Boolean

Return whether this concept is primitive. Host concepts are, by definition, never primitive, so false is returned for them.

const ClassicDescription& ClassicConcept::getDefinition() const
(getDefinition ClassicConcept) -> ClassicDescription

Return the classic description that was used to define the concept.

const HostDescription& HostConcept::getDefinition() const
(getDefinition HostConcept) -> HostDescription

Return the host description that was used to define the concept.

const NeoSet<Rule>& ClassicConcept::getRules () const
(getRules ClassicConcept) -> NeoSet<Rule>
(concept-rules ClassicConcept) -> NeoSet<Rule>©

Return the rules that are defined on this concept. Rules can only be defined on classic concepts, so host concepts will return an empty set.

c) Taxonomy Retrievals

NeoSet<ClassicConcep> ClassicConcept::getParents () const
(getParents ClassicConcept) -> NeoSet<ClassicConcep>
(concept-parents ClassicConcept) -> NeoSet<ClassicConcept>©

Return the minimal elements of the set of classic concepts in the knowledge base that subsume the concept.

NeoSet<ClassicConcept> ClassicConcept::getAncestors () const
(getAncestors ClassicConcept) -> NeoSet<ClassicConcept>
(concept-ancestors ClassicConcept) -> NeoSet<ClassicConcept>©

Return the maximal elements of the set of classic concepts in the knowledge base that subsume the concept.

NeoSet<ClassicConcept> ClassicConcept::getChildren () const
(getChildren ClassicConcept) -> NeoSet<ClassicConcept>
(concept-children ClassicConcept) -> NeoSet<ClassicConcept>©

Return the minimal elements of the set of classic concepts in the knowledge base that are subsumed by the concept.

NeoSet<ClassicConcept> ClassicConcept::getDescendants () const
(getDescendants ClassicConcept) -> NeoSet<ClassicConcept>
(concept-descendants ClassicConcept) -> NeoSet<ClassicConcept>©

Return the maximal elements of the set of classic concepts in the knowledge base that are subsumed by the concept.

NeoSet<ClassicConcept> ClassicConcept::getEquivalents () const
(getEquivalents ClassicConcept) -> NeoSet<ClassicConcept>

Return the set of classic concepts in the knowledge base that are equivalent to the concept (including the concept itself).

const NeoSet<ClassicIndividual>& ClassicConcept::getDirectInstances() const
(getDirectInstances ClassicConcept)
(concept-direct-instances ClassicConcept)©

Return the classic individuals in the knowledge base that are instances of the concept but not instances of any of its children.

NeoSet<ClassicIndividual> ClassicConcept::getInstances() const
(getInstances ClassicConcept)
(concept-instances ClassicConcept)©

Return the classic individuals in the knowledge base that are instances of the concept (including instances of any of its desendants).
*NOTE*: This function may construct and return a large set.

NeoSet<HostConcept> HostConcept::getParents() const
(getParents HostConcept) -> NeoSet<HostConcept>
(concept-parents HostConcept) -> NeoSet<HostConcept>©

Return the minimal elements of the set of host concepts in the knowledge base that subsume the concept.

NeoSet<HostConcept> HostConcept::getAncestors () const
(getAncestors HostConcept) -> NeoSet<HostConcept>
(concept-ancestors HostConcept) -> NeoSet<HostConcept>©

Return the maximal elements of the set of host concepts in the knowledge base that subsume the concept.

NeoSet<HostConcept> HostConcept::getChildren() const
(getChildren HostConcept) -> NeoSet<HostConcept>

Return the maximal elements of the set of host concepts in the knowledge base that are subsumed by the concept.

NeoSet<HostConcept> HostConcept::getDescendants () const
(getDescendants HostConcept) -> NeoSet<HostConcept>
(concept-descendants HostConcept) -> NeoSet<HostConcept>©

Return the maximal elements of the set of host concepts in the knowledge base that are subsumed by the concept.

NeoSet<HostConcept> HostConcept::getEquivalents () const
(getEquivalents HostConcept) -> NeoSet<HostConcept>

Return the set of host concepts in the knowledge base that are equivalent to the concept (including the concept itself).

7/ Rules

Rules represent simple forward-chaining rules that run only on named classic individuals in a domain.
class Rule : public Description

a) Simple Retrievals

const ClassicConcept& Rule::getAntecedent() const
(getAntecedent Rule) -> ClassicConcept
(rule-antecedent Rule) -> ClassicConcept©

Return the antecedent of the rule.

const RuleConsequent& Rule::getConsequent() const
(getConsequent Rule) -> RuleConsequent
(rule-consequent Rule) -> RuleConsequent©

Return the consequent of the rule.

b) Queries

Boolean Rule::inconsistent() const
(inconsistent Rule) -> Boolean

Return whether a rule is inconsistent. Inconsistent rules are never actually part of a knowledge base, but are instead used to represent relevant portions of the knowledge base that would have resulted from operations that would have made the knowledge base inconsistent.

const ClassicIndividual & Rule::getInconsistent() const
(getInconsistent Rule) -> ClassicIndividual

Return the classic individual where the inconsistency on a rule was discovered. This is only well-defined if the rule is inconsistent.

c) Rule Consequents

class RuleConsequent
class ClassicDescriptionConsequent : public RuleConsequent
class ComputedDescription : public RuleConsequent
class ComputedFillers : public RuleConsequent

The consequent of a rule can either be a classic description or the result of a user rule function.

static ClassicDescriptionConsequent ClassicDescriptionConsequent::create
(const ClassicDescription& r)

Create a rule consequent from a classic description.

static ComputedDescription ComputedDescription::create(const ComputedDescriptionGenerate * dtl,
const List<NeoObject> & params)
(computedDescription ComputedDescriptionGenerate [NeoObject...])
(computed-concept ComputedDescriptionGenerate [NeoObject...])©

static ComputedFillers ComputedFillers::create(const ComputedFillersGenerate * dtl,
const List<NeoObject> & params)
(computedFillers ComputedFillersGenerate [NeoObject...])
(computed-fillers ComputedFillersGenerate [NeoObject...])©

Create a rule consequent from a user rule function and a list of parameters.

8/ Classic Individuals

class ClassicIndividual : public NeoPtrObject

Classic individuals represent classic objects in a domain.

a) Simple Retrievals

const ClassicDescription& ClassicIndividual::getDefinition() const
(getDefinition ClassicIndividual) -> ClassicDescription
(individual-descriptor ClassicIndividual) -> ClassicDescription©

Return the current definition of the classic individual.

b) Adding and Removing Information from Classic Individuals

Another way of modifying the information in a knowledge base is by adding and removing information from the classic individuals in the knowledge base.

[INCONSISTENT return] If any of these operations would make the knowledge base inconsistent, the operation is not performed. Instead an inconsistent classic individual is returned. This classic individual contains the relevant inconsistent state of the knowledge base that would have resulted from performing the operation.

ClassicIndividual ClassicIndividual::addToldInformation (const ClassicDescription&)
(addToldInformation ClassicIndividual ClassicDescription) -> ClassicIndividual
(individual-add ClassicIndividual ClassicDescription) -> ClassicIndividual©

Add information to a classic individual.

ClassicIndividual ClassicIndividual::removeToldInformation (const ClassicDescription&)
(removeToldInformation ClassicIndividual ClassicDescription) -> ClassicIndividual
(individual-remove ClassicIndividual ClassicDescription) -> ClassicIndividual©

Remove previously told information from a classic individual. If information being removed is not on the individual, do nothing.

ClassicIndividual ClassicIndividual::closeRole(const Role&)
(closeRole ClassicIndividual Role) -> ClassicIndividual
(individual-close-role ClassicIndividual Role) -> ClassicIndividual©

Close a role on a classic individual. Note that it is not an error to close a role twice. Also, closing a role with fewer known fillers than the mininum derived number of fillers for that role will result in an inconsistent object.

ClassicIndividual ClassicIndividual::uncloseRole(const Role&)
(uncloseRole ClassicIndividual Role) -> ClassicIndividual
(individual-unclose-role ClassicIndividual Role)->ClassicIndividual©

Unclose a previously-closed role on a classic individual. Note that it is not an error to unclose a role that was not closed.

c) Queries

Boolean ClassicIndividual::inconsistent() const
(inconsistent ClassicIndividual) -> Boolean

Return whether a classic individual is inconsistent. Inconsistent individuals are never actually part of a knowledge base, but are instead used to represent relevant portions of the knowledge base that would have resulted from operations that would have made the knowledge base inconsistent.

d) Taxonomy Retrieval

NeoSet<ClassicConcept> ClassicIndividual::getParents () const
(getParents ClassicIndividual) -> NeoSet<ClassicConcept>
(individual-parents ClassicIndividual) -> NeoSet<ClassicConcept>©

Return the minimal elements of the set of classic concepts in the knowledge base of the individual that have the individual as an instance.

e) Told Retrievals

The following functions retrieve various information that was TOLD about the individual. In several cases there are two versions of a function, one that returns a set of the told information and one that returns this told information combined into one piece.

NeoSet<ClassicConcept*gt; ClassicIndividual::toldParents() const
(toldParents ClassicIndividual) -> NeoSet< (individual-told-parents ClassicIndividual) -> NeoSet<ClassicConcept*gt;©

NeoSet<unsigned int> ClassicIndividual::toldAtLeasts(const Role &) const
(toldAtLeasts ClassicIndividual Role) -> NeoSet<unsigned int>

unsigned int ClassicIndividual::toldAtLeast(const Role &) const
(toldAtLeast ClassicIndividual Role) -> unsigned int

NeoSet<unsigned int> ClassicIndividual::toldAtMosts(const Role &) const
(toldAtMosts ClassicIndividual Role) -> NeoSet<unsigned int>

unsigned int ClassicIndividual::toldAtMost(const Role &) const
(toldAtMost ClassicIndividual Role) -> unsigned int

IndividualSet ClassicIndividual::toldFillers(const Role &) const
(toldFillers ClassicIndividual Role) -> IndividualSet

NeoSet<Description> ClassicIndividual::toldValueDescriptions(const Role&)const
(toldValueDescriptions ClassicIndividual Role)-> NeoSet<Description>

Description ClassicIndividual::toldValueDescription(const Role &) const
(toldValueDescription ClassicIndividual Role) -> Description

NeoSet<NeoSet<ClassicIndividual>> ClassicIndividual::toldOneOfs() const
(toldOneOfs ClassicIndividual) -> NeoSet<NeoSet<ClassicIndividual>>

ClassicOneOf ClassicIndividual::toldOneOf() const
(toldOneOf ClassicIndividual) -> ClassicOneOf

NeoSet<ClassicTest> ClassicIndividual::toldTests() const
(toldTests ClassicIndividual) -> NeoSet<ClassicTest>
(individual-told-tests ClassicIndividual) -> NeoSet<ClassicTest>©

Boolean ClassicIndividal::roleClosed(const Role &) const
(roleClosed ClassicIndividual Role) -> Boolean
(individual-closed-role? ClassicIndividual Role) -> Boolean©

Individuals can also have their role closed. The previous function determines whether a particular role was closed on the individual. Note that this is different from having a full role.

f) Derived Retrievals

The following functions retrieve various information that was DERIVED about the individual, that is a combination of the told information plus any information that could be inferred.
NeoSet<ClassicConcept> ClassicIndividual::derivedPrimitives() const
(derivedPrimitives ClassicIndividual) -> NeoSet<ClassicConcept>

unsigned int ClassicIndividual::derivedAtLeast(const Role &) const
(derivedAtLeast ClassicIndividual Role) -> unsigned int
(individual-role-description-min ClassicIndividual Role) -> unsigned int©

unsigned int ClassicIndividual::derivedAtMost(const Role &) const
(derivedAtMost ClassicIndividual Role) -> unsigned int
(individual-role-description-max ClassicIndividual Role) -> unsigned int©

IndividualSet ClassicIndividual::derivedFillers(const Role &) const
(derivedFillers ClassicIndividual Role) -> IndividualSet
(individual-role-fillers ClassicIndividual Role) -> IndividualSet©

Description ClassicIndividual::derivedValueDescription(const Role &) const
(derivedValueDescription ClassicIndividual Role) -> Description
(individual-role-description-value ClassicIndividual Role)-> Description©

ClassicOneOf ClassicIndividual::derivedOneOf() const
(derivedOneOf ClassicIndividual) -> ClassicOneOf

NeoSet<ClassicTest> ClassicIndividual::derivedTests() const
(derivedTests ClassicIndividual) -> NeoSet<ClassicTest>
(individual-tests ClassicIndividual) -> NeoSet<ClassicTest>©

Boolean ClassicIndividual::derivedFullRole() const
(derivedFullRole ClassicIndividual Role) -> Boolean

9/ Host Individuals and related classes

The class HostIndividual is used to represent host programming elements of the domain. The classes MinOrMax and IntOrFloat are used internally by NeoClassic, but are also visible in the C++ application programming interface. All three classes share a common implementation, so they are discussed together here.

class MinOrMax

A class used to hold an integer or real number, or positive or negative infinity. (Actually MinOrMax can also hold a String, because it is a superclass of HostIndividual, but this is never used.)

MinOrMax::MinOrMax(int value)
MinOrMax::MinOrMax(float value)
static MinOrMax::infiniteMinimum()
static MinOrMax::infiniteMaximum()

Create a value of class MinOrMax.

HostType MinOrMax::getType() const

Return the type of value stored in a MinOrMax

operator MinOrMax::int() const
operator MinOrMax::float() const

Coerce a MinOrMax value into an int or float. If the value in the MinOrMax is not of the appropriate type, some "neutral" value is returned.

Boolean MinOrMax::isInfinity() const

Return whether the MinOrMax is an infinite value

class HostIndividual : public MinOrMax

Host individuals represent elements of the domain taken from the host programming language. Currently these elements must be strings, integers, or real numbers. Host individuals that are not strings can be compared as numbers.

HostIndividual::HostIndividual(int value)
HostIndividual::HostIndividual(float value)
HostIndividual::HostIndividual(const String& value)

Create a value of class HostIndividual.

HostType HostIndividual::getType() const

Return the type of the host individual.

operator HostIndividual::int() const
operator HostIndividual::float() const
operator HostIndividual::String() const

Coerce a host individual back to an int, float, or string. If the host individual is not of an appropriate type, some "neutral" value is returned.

class IntOrFloat : public HostIndividual

A class used to hold an integer or real number.

IntOrFloat::IntOrFloat(int value)
IntOrFloat::IntOrFloat(float value)

Create a value of class IntOrFloat

HostType IntOrFloat::getType() const

Return the type of the IntOrFloat.

operator IntOrFloat::int() const
operator IntOrFloat::float() const

Coerce an IntOrFloat back to an integer or real number. If the IntOrFloat is not of an appropriate type, some "neutral" value is returned.

10/ User Functions

class ClassicTestGenerate
class HostTestGenerate
class ComputedDescriptionGenerate
class ComputedFillersGenerate
class ClassicTestDetail
class HostTestDetail
class ComputedDescriptionDetail
class ComputedFillersDetail
class ClassicTest
class HostTest

Note: Most of these classes are actually template instantiations, but this implementation detail does not affect their use.

User Functions are C++ functions that are called at appropriate places within NeoClassic, and are used to extend the functionality of NeoClassic. There are two kinds of user functions: test functions, which extend descriptions; and rule functions, which extend rules.

Each kind of user function is actually a subclass of ClassicTestDetail, HostTestDetail, ComputedDescriptionDetail, or ComputedFillersDetail. Creating a user function involves calling the create member function of a subclass of ClassicTestGenerate, HostTestGenerate, ComputedDescriptionGenerate, or ComputedFillersGenerate. The creation function takes a collection of parameters, which are stored in the new instance of a subclass of ClassicTestDetail, HostTestDetail, ComputedDescriptionDetail, or ComputedFillersDetail. Running the user function involves calling the run member function of this new instance. This member function can access the information retained in the instance.

The different user functions have different behavior, based on where the object they are embedded in is placed in NeoClassic.

ClassicTestDetail and HostTestDetail are placed in descriptions created by testC and testH, respectively. Their run functions are responsible for determinining whether a classic or host individual is known to belong to the test description, in which case the function returns testTrue; whether the individual is known not to belong to the description, in which case it returns testFalse; or whether the individual is neither known to belong nor not known to belong, in which case it returns testMaybe. Once a ClassicTestDetail or HostTestDetail is placed in a description, it is no longer directly accessible but its data can be retrieved in the application programming interface via the ClassicTest and HostTest classes that are returned from the toldTests and derivedTests functions.

const Symbol & ClassicTest::getName() const
const Symbol & HostTest::getName() const

Return the name of a test.

List<NeoObject> ClassicTest::getArguments() const
List<NeoObject> HostTest::getArguments() const

Return the arguments for a test.

ComputedDescriptionDetail and ComputedFillersDetail are placed in the consequent of rules. They are responsible for determining the description to be added to a classic individual as a result of running the rule. The run function for ComputedDescriptionDetail returns this classic description directly, whereas the run function for ComputedFillersDetail returns an IndividualSet that is added to the fillers of a role on the individual. This role is the role that was specified as the first parameter for the ComputedFillersDetail.

The character interface creates user functions by means of tables that map symbols into user function prototype. These prototypes are instances of the ...Generate classes, and are responsible for checking if the parameters supplied are appropriate, for creating new user functions, and for generating usage messages.

There are four built-in user functions that can be used in the character interface without doing any C++ programming. They are all HostTestGenerate functions that are used to create host test descriptions.

  	Character Interface Name	Description

	numberp			is a host individual a number?
	integerp		is a host individual an integer?
	floatp			is a host individual a float?
	stringp			is a host individual a string?

Most of the work of defining kinds of user functions is done by macros and templates. The only function that has to be written by users is the run function.

Consider this example:

	ClassicTestFunction2(AtLeastTest,atLeast,unsigned int,Role);

	TestVal AtLeastTest::run(const ClassicIndividual& ind,
				 Set<ClassicIndividual> *,
				 Set<ClassicIndividual> *) const {
	  ClassicIndividualDescription def = ind.getDefinition();
	  unsigned int indmin = def.derivedAtLeast(arg2);
	  unsigned int indmax = def.derivedAtMost(arg2);
	  if (indmin >= arg1) {
	    return testTrue;
	  } else if (indmax < arg1) {
	    return testFalse;
	  } else {
	    return testMaybe;
	  }
	}
The macro ClassicTestFunction2 creates a subclass of ClassicTestDetail, AtLeastTest. This subclass has a data member called arg1 with type unsigned int and a data member called arg2 with type Role.

The macro also creates a prototype object that is an instance of (a subclass of) ClassicTestGenerate. The prototype ensures that a creation of an AtLeastTest via a call to testC has two parameters, and that the first one can be converted into an unsigned int and that the second one can be converted into a Role. The create function of the prototype converts the parameters to the correct type, if necessary, and determines which knowledge base, if any, the description will belong to. Then the create function calls a constructor for AtLeastTest that stores the name, knowledge base, and parameters in the new instance. Finally the create function returns the new instance of AtLeastTest. The usage function of the prototype print an appropriate string.

The macro provides a number of member functions for the AtLeast class. The == member operator that the name and all the parameters are the same. The print member function prints the name and the parameters. The getKB and getName member functions return the stored knowledge base and name.

The run member function has to be supplied by the user, as above. This run member function takes a classic individual and two pointers to sets, and returns a TestVal, as do all ClassicTestFun1ctions. The run member function here checks to see if there are enough fillers for the role parameter on the individual. It ignores the set pointers, which are used to communicate dependencies, as it does not produce any dependencies.

The following macros are defined for creating user functions. Each create data members, argi, for each parameter. Note that ComputedFillers has an implicit first parameter, which is a role. The meaning of the suffix on the macros is the number of parameters, followed by L if a list of the trailing parameters is wanted.

The above macros both declare and define the user function. To be able to refer to the user function in more than one file, there are declaration and definition versions of the above macros. The declaration versions have the above names suffixed with Declare; the definition versions are suffixed with Define.

The run functions have the following signature

	virtual TestVal 
	ClassicTestDetail::run(const ClassicIndividual& ind,
			       Set<ClassicIndividual>* pdeps,
			       Set<ClassicIndividual>* ndeps) const

	virtual TestVal 
	HostTestDetail::run(const HostIndividual& ind) const

	virtual ClassicDescription 
	ComputedDescriptionDetail::run(const ClassicIndividual& ind) const

	virtual IndividualSet
	ComputedFillersDetail::run(const ClassicIndividual& ind) const
These run functions have a number of severe descriptions placed on them. First, they must not modify the knowledge base. Second, the test functions must be monotonic---that is, if they return testTrue or testMaybe they must return the same result in a knowledge base with more information. Third, the rule functions must be constant---that is, they must return the same answer in a knowledge base with more information. Fourth, if adding information to some other classic individual could cause an answer returned from a classic test function, then that individual must be added to the pdeps argument, provided that that argument is non-null; if removing information from some other classic individual could cause an answer returned from a classic test function, then that individual must be added to the ndeps argument, provided that that argument is non-null.

Underlying the above macros are the following member functions for the ...Generate and ...Detail classes.

On the ...Generate side there is:

virtual int incompatible (const List<NeoObject> & form) const

This function takes a form and determines whether it is suitable for the particular kind of user function. The form is the entire form that is being evaluated, starting with the name of the character interface function, then a pointer to the prototype being run, then the parameters for the user function creation. This function is called by the evaluator before the create function is run.

Values to return are

0
if everything is OK
+n
if the n'th arg cannot be converted
-n
if the n'th arg can be converted several ways
tooManyArguments
too many arguments supplied
tooFewArguments
too few arguments supplied
otherProblem
some other problem

virtual ...Detail * create(const List<NeoObject> & parameters) const

This function takes a list of parameters and creates the actual user function.

virtual void usage ( const NeoForm & form, ostream & os ) const

Print a usage message for this kind of user function. This function is called by the evaluator when the parameters are determined to not be compatible with the user function.

On the ...Detail side there is:

virtual int operator ==(const UserFunctionDetail<RESULT,INDS> &) const

This function determines whether two user functions are equal.

virtual void print(ostream & os) const

Print a user function on a stream.

KnowledgeBase getKB() const

Return the knowledge base associated with a user function.

Symbol getName() const

Return the name of the user function.

virtual ... run(...) const

This function does the actual work for the user function.

11/ Errors

There are four kinds of errors in NeoClassic. The first two kinds of errors are specific to the character interface, and encompass anything that can go wrong there. (See the documentation on the character interface for more on these kinds of errors.) The third kind of error is illegal calls to NeoClassic functions, such as trying to return the role that has a particular name when there is no such role. The fourth kind of error is an actual knowledge error, such as trying to add information to a classic individual that makes the knowledge base inconsistent.

There is a fifth kind of ``unusual'' return from NeoClassic that is not really an error. This return value is an incoherent description. There is nothing wrong with creating an incoherent description unless that description is used as the definition of a concept or individual, so this return does not by itself signal an error.

Illegal calls to NeoClassic functions generally result in null returns. Illegal calls to NeoClassic include:

Knowledge errors result in returned objects that are incoherent or inconsistent. The requested operation is not performed, i.e., the knowledge base is not changed. Explanation can be used to determine why the object is incoherent or inconsistent. Calls that produce knowledge errors include:

12/ Explanation

Explanation is in the process of being implemented. Documentation will be provided when explanation is complete.

13/ Hooks

Hooks are designed to allow a User Interface, or some other program, to monitor the changes to a NeoClassic knowledge base. They allow user functions to be run in response to knowledge base changes. Hooks are implemented as a collection of function pointers, to reduce overhead, as data members of the class Hook, to reduce namespace pollution.

To incorporate your hooks into NeoClassic, create a file with the hook functions you require. Assign pointers to these functions to the appropriate members of the class Hook. You have to assign values for all the members of the class Hook given below; unused hooks can be set to 0.

There are two different kinds of changes that can be monitored, requests to add or remove information from the knowledge base and deductions made in response to these requests. The former kinds of changes may be rejected by NeoClassic because they would make the knowledge base inconsistent or create an incoherent concept. Therefore, there are several hooks for each such change. The latter kinds of changes just happen, but it is possible for several deductions to be made in response to a request, an inconsistency discovered, and then the changes undone.

a) User Request Hooks

The hooks that monitor most requests come in threes, one that signals the start of the request, that is when the request is started to be performed; and two that monitor the end of the request, one that signals successful request and one that signals failed requests. Some requests never fail and so have only two hooks; some happen indivisibly and so only have one hook. Requests that are rejected for name-space reasons, such as trying to create a concept with a name that is already in use in the knowledge base, do not cause any hook to be called.

Hooks that signal the creations of objects in a knowledge base have as arguments the knowledge base in which the request is being made, the name of the new object, and the creation arguments. Hooks that signal the end of such requests have as argument the new object, which is an error object for failed requests.

static void (*Hooks::createKnowledgeBase)(const KnowledgeBase &kb)
static void (*Hooks::destroyKnowledgeBase)(const KnowledgeBase &kb);

These two hooks monitor the creation and destruction of knowledge bases. The first is run after the knowledge base is added to the collection of knowledge bases; the second is run after the knowledge base is removed from the collection of knowledge bases.

static void (*Hooks::startCreateRole)(const KnowledgeBase &kb, const Symbol & name,
const Boolean & attribute);
static void (*Hooks::successCreateRole)(const Role &role);

These two hooks monitor the creation of roles.

static void (*Hooks::startCreateClassicConcept)(const KnowledgeBase &kb, const Symbol & name,
const ClassicDescription & def, const Primitive & primitive);
static void (*Hooks::successCreateClassicConcept)(const ClassicConcept &);
static void (*Hooks::failureCreateClassicConcept)(const ClassicConcept &);

static void (*Hooks::startCreateHostConcept)(const KnowledgeBase &kb, const Symbol & name,
const HostDescription & def);
static void (*Hooks::successCreateHostConcept)(const HostConcept &concept);
static void (*Hooks::failureCreateHostConcept)(const HostConcept &concept);

These hooks monitor the creation of classic and host concepts.

static void (*Hooks::startCreateRule)(const KnowledgeBase &kb, const Symbol & name,
const ClassicConcept & antecedent, const RuleConsequent & consequent);
static void (*Hooks::successCreateRule)(const Rule &rule);
static void (*Hooks::failureCreateRule)(const Rule &rule);

These hooks monitor the creation of rules.

static void (*Hooks::startCreateClassicIndividual)(const KnowledgeBase &kb, const Symbol & name,
const ClassicDescription & def);
static void (*Hooks::successCreateClassicIndividual)(const ClassicIndividual &ind);
static void (*Hooks::failureCreateClassicIndividual)(const ClassicIndividual &ind);

These hooks monitor the creation of classic individuals.

static void (*Hooks::startAddToldInformation)(const ClassicIndividual &ind,
const ClassicDescription & info);
static void (*Hooks::successAddToldInformation)(const ClassicIndividual &ind,
const ClassicDescription & info);
static void (*Hooks::failureAddToldInformation)(const ClassicIndividual &ind,
const ClassicDescription & info);

static void (*Hooks::startRemoveToldInformation)(const ClassicIndividual &ind,
const ClassicDescription & info);
static void (*Hooks::successRemoveToldInformation)(const ClassicIndividual &ind,
const ClassicDescription & info);
static void (*Hooks::failureRemoveToldInformation)(const ClassicIndividual &ind,
const ClassicDescription & info);

These hooks monitor the addition and removal of information from classic individuals. The completion hooks have as extra argument the information added or retracted.

static void (*Hooks::startCloseRole)(const ClassicIndividual &ind, const Role & r);
static void (*Hooks::successCloseRole)(const ClassicIndividual &ind, const Role& r);
static void (*Hooks::failureCloseRole)(const ClassicIndividual &ind, const Role& r);

static void (*Hooks::startUncloseRole)(const ClassicIndividual &ind, const Role& r);
static void (*Hooks::successUncloseRole)(const ClassicIndividual& ind, const Role&r);
static void (*Hooks::failureUncloseRole)(const ClassicIndividual& ind, const Role&r);

These hooks monitor the closing and unclosing of roles on classic individuals. The completion hooks have as extra argument the role being closed or unclosed. In the unclosing case, the hooks are only called if the role was initially closed.

b) Deduction Hooks

The hooks that monitor deductions are called when the deductions are made, i. e., when NeoClassic is in the middle of processing a request. This means that the knowledge base is in an unsual state---some deductions will be made and others will not. Therefore these hook functions have to be particularly careful. In particular, such a hook function should not change the knowledge base in ANY way. Any violation of this requirement is likely to result in malformed knowledge bases, core dumps, or infinite loops. Accessing the knowledge base is allowed, but the exact current state of the knowledge base will be seen, so there may be inconsistent individuals in the knowledge base, etc., etc. Further, the points at which the hook functions are called and the arguments passed have been chosen to minimize the impact on NeoClassic.
static void (*Hooks::addParents)(const ClassicIndividual & ind, const ClassicConcept & parent,
const Set<ClassicConcept> & otherParents);

This hook is called when a group of new parents is discovered for an individual. Both parent and otherParents are being added.

static void (*Hooks::removeParents)(const ClassicIndividual & ind, const Concept & parent,
const Set<Concept> & otherParents);

This hook is called when a group of concepts are no longer parents for an individual because more-specific parents have been found. Both parent and otherParents are being removed. This hook is not called when all derived information is being removed from an individual!

static void (*Hooks::propagation)(const ClassicIndividual & to, const ClassicDescription & what,
const RolePath & path, const ClassicIndividual & from);

This hook is called when a propagation of information from one individual to another occurs.

static void (*Hooks::ruleFiring)(const ClassicIndividual & ind, const Rule & rule,
const ClassicDescription & consequent);

This hook is called when a new rule is run on an individual. The third argument is the actual description being added to the individual.

static void (*Hooks::removeDerived)(const ClassicIndividual & ind);

This hook is called when the derived information, including taxonomy information, on an individual has to be recomputed, either because an inconsistency was discovered or told information is being removed or a role is being unclosed. Part of removing derived information is removing the parents of an individual; this removal is not separately signalled.

14/ Environmental Concerns

The class NeoEnvironment, which has only static members, contains several functions relating to the environment of NeoClassic. These functions are only available through the API, as they must be performed outside of the character interface, or have analogues inside the character interface.

static void NeoEnvironment::init()
static void NeoEnvironment::init(const String &outfn, const String &errfn)

Initialize the NeoClassic environment. This must be called before any other NeoClassic function, and should not be called until after cleanup is called. The first version sets the output and error streams to cout and cerr, the second sets them to write to the given file names (which can be the same).

static void NeoEnvironment::cleanup()

Cleanup the NeoClassic environment. No NeoClassic functions can be called after this function is called, unless NeoClassic::init is again called.

static void NeoEnvironment::readFile(const String & filename)

Read and process a file in the character interface.

static void NeoEnvironment::readFile()

Read and process the standard input in the character interface.

15/ Future Functionality

The following functionality will be supported in future releases of NeoClassic:

Character Interface

The NeoClassic Character Interface is a simple interface that allows access to the capabilities of NeoClassic without having to write C++ code. The character interface reads commands from a stream, evaluates these commands, and (optionally) prints the results obtained.

The functions in the character interface are described in the interface documentation.

1/ Input Syntax

The character interface inputs a sequence of forms, in the following grammar:
Form          ::=  LispModeForm  |  CModeForm
LispModeForm  ::=  (Symbol LispModeArg*)
LispModeArg   ::=  Variable | Boolean | Int | Float | 
		   String | Symbol | KBSymbol | 
		   LispModeForm
CModeForm     ::=  Symbol ( CModeArg* )
CModeArg      ::=  Variable | Boolean | Int | Float | 
		   String | Symbol | KBSymbol | 
		   CModeForm

Boolean       ::=  `true' | `false'
Int	      ::=  [`+'|`-']Digit+
Float	      ::=  [Int]`.'Digit*
String        ::=  `"'Char*`"'
variable      ::=  `$'char*
Symbol        ::=  Alpha AlphaDigit*
KBSymbol      ::=  Symbol`:'Symbol
Alpha	      ::=  `a'|`b'|`c'|...|`z'|`A'|`B'|`C'|...|`Z'|`?'|...
AlphaDigit    ::=   Alpha | `0' | ... | `9'
Abmiguities are resolved by taking the first alternative. (That is, the argument `$A' is a Variable, not a Symbol; and the argument `true' is a Boolean, not a Symbol.)

The syntax for the CI allows two ways of grouping a function with its arguments. Parentheses may be placed around the arguments only or parentheses may be placed around the function name as well as the arguments. Many CI functions can take an arbitrary number of arguments that are grouped into a set or list.

2/ Evaluation

A form is evaluated by first evaluating its arguments. Then all character interface functions for the first symbol in the form that are compatible with the actual arguments in the form are found. If there is exactly one, it is executed on these arguments.

A character interface function is compatible with a list of arguments if the arguments can be converted into the types of objects that the function wants. If the function has a Set or List as its last argument, a Set or List is made from the sequence of trailing actual arguments.

Variables are replaced by their values before evaluation starts.

3/ Special Functionality

In the character interface, more-general classes are conditionally coerced into more-specific classes. For example, if a function requires a ClassicDescription, but its argument produces a Description, the Character Interface will check to see if the result of evaluating the argument is actually a ClassicDescription, and will coerce it if so. If the result is not a ClassicDescription, the character interface will report an error.

Other conversions are also performed, including

Symbols are conditionally converted into NeoPtrObject, Role, Concept, ClassicConcept, HostConcept, or Rule, by looking them up in the current knowledge base. KBSymbols are conditionally converted into NeoPtrObject, Role, Concept, ClassicConcept, HostConcept, or Rule, by looking them up in their knowledge base. Symbols are conditionally converted into ClassicTestDetail, HostTestDetail, ComputedDescriptionDetail, or ComputedFillersDetail by looking the symbol up in the appropriate table.

In addition, the fills and oneOf functions will automatically create ClassicIndividuals if given a symbol for which no classic individual exists.

Operations that are member functions of KnowledgeBase work on the current knowledge base in the character interface, so no knowledge base ``argument'' is required.

Variables can be set and retrieved. The values of the last three forms that produced values are available as the values of the variables $, $$, and $$$.

4/ Printing

The different types of objects in the character interface and their printed representation are as follows:
  Type				Printed Representation

  int				sequence of numerals
  float				sequence of numerals and .
  Boolean			false or true
  String			sequence of characters
  Symbol			sequence of characters
  KBSymbol			two sequences of characters separated by :

  NeoSet<TYPE>			elements enclosed in { and }
  IndividualSet			elements enclosed in { and }
  ClassicOneOf			<Universe> or elements enclosed in { and }
  HostOneOf			<Universe> or elements enclosed in { and }

  MinOrMax			+INF, -INF, or as int or float
  HostIndividual		as int or float or String
  IntOrFloat			as int or float

  Primitive			false, true, or set of symbols

  RuleConsequent		form that is equivalent to the consequent
  ClassicTestGenerate		name of the generator
  HostTestGenerate		name of the generator
  ComputedDescriptionGenerate	name of the generator
  ComputedFillersGenerate	name of the generator

  KnowledgeBase			name of the knowledge base
  Description			form that is equivalent to the description
  Role				(primary) name of the role
  Concept			(primary) name of the concept
  Rule				(primary) name of the rule
  ClassicIndividual		(primary) name of the classic individual
Further, if a Concept is incoherent, or a Rule or ClassicIndividual is inconsistent, the inference that caused the incoherency or inconsistency is shown when the object is printed as the result of evaluation.

5/ Errors

Parsing and evaluating errors are signalled by printing an error message on the standard error. If input is from a file, this message includes the file name and line number where the error was detected

Parsing errors indicate a problem with parsing the input. Forms that have parsing errors are not evaluated. As soon as a parse error is detected the rest of the input line is discarded. Parsing errors include:

Evaluator errors indicate a problem with evaluating a form. As soon as an evaluator error occurs, the evaluation of the entire form is aborted. Evaluator errors include:

User functions do their own compatability checking, initiated by the evaluator. If the user function is not compatible with the supplied parameters this is considered an evaluator error.

NeoClassic errors indicate some problem within NeoClassic. These are not necessarily real errors, but instead may indicate some sort of exceptional condition in a NeoClassic knowledge base. NeoClassic errors include:

A non-existant NeoPtrObject return generally indicates some sort of problem having to do with the name space of a knowledge base, such as trying to look up a non-existent concept or trying to create a role with a name that is already used for another role. An incoherent NeoPtrObject return indicates some operation that would have created an incoherent concept. An inconsistent NeoPtrObject return indicates some operation that would have made a knowledge base inconsistent. In both these two latter cases the operation is not performed. See the documentation on individual NeoClassic operations for more information on NeoClassic errors.

6/ Special Functions

(readFile String)
(load String)

Read and evaluate from the file whose name is String. At end of file or quit revert back to the current input stream.

(setPrinting Boolean)

Turn printing on or off when reading from a file.

(set Symbol NeoObject)

Set the value of the variable with name Symbol to NeoObject.

(select NeoObject unsigned int) -> NeoObject

Select an element from a NeoObject that is (like a) set. The elements are most likely to be counted in printing order, but there are NO guarantees! If the NeoObject is not like a set or does not have enough elements the NeoObject itself is returned.

(print NeoObject)

Send the print version of the item to the current output.

(printInfo Role)
(printInfo Concept)
(printInfo Rule)
(printInfo ClassicIndividual)

Send information on the object to the current output.

(explain Concept)
(explain ClassicIndividual)

Calculate the inferences which produced all the information in the object. Print the result in a structured manner, and only print the relevant inferences (not those which were overridden).

(explainVerbose Concept)
(explainVerbose ClassicIndividual)

Calculate the inferences which produced all the information in the object. Print all the inferences, in an unstructured manner.

(quit)
(exit)
(bye)

If reading from a file, quit reading from that file. If not inside a readFile, quit NeoClassic.

7/ Testing Functions

The following functions are used for testing the correct behavior of NeoClassic, and should not be used in normal code.
(testResult NeoObject NeoObject [String])
(testResultSet NeoObject NeoObject...)

Determine if the two non-string arguments are the same. If not, print an error message (for testResult). testResultSet is defined on only certain kinds of NeoObjects, namely those that are like sets.