Error Reporting - Knowledge Representation Use
It is useful to report warnings and errors on the use of a knowledge representation language. For example, KR queries that do not have corresponding definitions will generate runtime errors and KR definitions that are not used are redundant. Both can be detected using static analysis. We thus want to detect whether KR expressions that are used have been declared or defined and, vice versa, that expressions that have been declared or defined are used.
We first need to identify what we should classify as an error and what should be classified as a warning. We distinguish between warnings and errors related to the use of variables and terms and those related to the use of formulas (queries, updates, and database formulas). Because we can only make few assumptions on the structure of the KR language, we need to delegate identifying unused and undefined expressions to the KR interface and the problem here is to identify what support a KR interface should offer to make reporting of warnings and errors possible. In other words, the problem is to identify the support we need to identify KR expressions in an agent program or module that are used but have not been defined or declared and vice versa. For variables and terms, we need to identify whether variables have been properly bound in action parameters, for example. The latter problem is relatively straightforward and here we discuss only error reporting related to formulas. In our discussion below we assume a global scope of the use of KR expressions and do not consider local scopes.
Definitions, Declarations, and Use of Expressions
It is difficult to precisely distinguish expressions in a KR language that are used as definitions, declarations, or otherwise (e.g., as query) without a clear notion of what the KR language looks like. We nevertheless want to distinguish these three categories of expressions below in general to be able to explain our approach to issuing warnings and errors related to a KR language. Informally, a definition is an expression E that is defined in terms of other expressions that are used to define expression E (think, for example, of a rule or clause in Prolog where the head is defined in terms of the body of the clause); a declaration is the explicit introduction of an expression which indicates that the expression can be used elsewhere in the agent program (e.g., by an insert action that inserts some predicate into the belief base of an agent). Other types of expressions such as queries indicate that an expression is used; typically, such uses need to be supported by either definitions or declarations. It is only possible to classify particular expressions as definitions, declarations, or other types of expressions by means of the categorization of expressions used by a KR technology itself; in other words, knowledge of the types of expressions present in a KR language is needed to be able to distinguish these categories.
Knowledge
The knowledge base of an agent consists of database formulas. These formulas may introduce definitions or contain declarations. Expressions that are defined in the knowledge base should be used somewhere but not necessarily within the knowledge base itself. Definitions may also be used, for example, in the belief and/or goal base. Database formulas may also entail the use of expressions (e.g., the expressions that define another expression are used). Expressions that are used in the knowledge base do not need to be defined or declared in the knowledge but may also have been defined in the belief or goal base of an agent.
The use of an expression in the knowledge base of an agent is supported if there is a corresponding definition or declaration in an agent program. A supporting definition or declaration can be introduced in two different ways. First, definitions can be present in the knowledge, belief, or goal base. Second, an expression can be (implicitly) declared by adding it to the belief or goal base of an agent (by means of an insert or adopt action).
A definition or declaration in the knowledge base is useful only if it is used somewhere in an agent program. Definitions or declarations can be used in two different ways. First, they can used in the expressions used to introduce (other) definitions in either the knowledge or belief base (the goal base cannot be used to introduce definitions). Second, they can be used by queries that occur in the goal base (each goal is queried against the belief base to verify whether it has been achieved; we also need to include goals that are introduced dynamically at runtime by adopt actions), or by belief queries (where we need to include a-goal and goal-a queries which are defined in terms of a belief query). If a definition or declaration is not used, we want to issue a warning because the definition or declaration is redundant; we do not want to issue an error because we do not expect any runtime problems.
In summary, we have the following conditions that should hold for the knowledge base:
- each expression use in the knowledge base should have a corresponding definition or declaration. These should be present either in the knowledge, the belief, or the goal base in an agent program. Supporting declarations can also be introduced by means of insert or adopt actions. If supporting definitions or declarations are missing, we want to issue an error (the missing information may cause serious runtime problems).
- each definition or declaration in the knowledge base should have a corresponding use in either the knowledge, the belief, or the goal base in an agent program. Definitions or declarations may also be used by belief queries (explicit or implicit as part of a-goal and goal-a queries). Finally, definitions and declarations may also be used by goals that are adopted. If that is not the case, we should issue a warning (the definition or declaration only is redundant, but no runtime problems are expected).
It is clear that it is important to be able to classify expressions as either definitions, declarations, or otherwise to be able to check the conditions above. Because we cannot do this classification of expressions without knowledge of the representation language that is used we need to delegate that job to the KR technology. (The problem is that we do not know which parts of a database formula are defined and which parts are used as definition; note that we do not have access to the structure of a formula at all.) In order to be able to check the two conditions above, we need a KR interface that provides two methods:
- getUnusedDfs(, )
- getUndefined(, )
The first method getUnusedDfs identifies and returns the definitions and/or declarations in that have not been used by expressions in or by uses implicit in . The second method getUndefined identifies and returns the use of expressions that have not been defined or declared.
Moreover, because we should not mix the use of expressions that combine belief and knowledge and those that combine knowledge and goals (a belief query uses expressions but never those that occur in a goal base), we need to distinguish these as well. We then find that we need to delegate the following method calls to the KR interface:
- getUnusedDfs(knowledge + beliefs + inserts (additions), belief queries + preconditions + goals + adopts)
- getUnusedDfs(knowledge + goals + adopts (additions), goal queries + goals + adopts)
It is important to realize that we also need to include and consider a-goal and goal-a queries as belief queries here because they are defined in terms of beliefs. Similarly, postconditions of user-defined actions and delete actions should also be considered in the first call because these can also add content to a database. We also need to check whether what is returned by the second method call has already been included in the first call as we do not want to report twice that a definition is not used.
We need to add a check to not report a definition D in the knowledge base as unused if it is not used by the goal base or a goal query but it is used by belief queries or implicitly in the belief base, and vice versa. That is, a definition in the knowledge base should only be reported as unused if both the belief and goal base and the belief and goal queries do not use it. In order to check this, we need to check that D is defined in the knowledge base (and not, for example, in the goal base). We can do this by checking that D is returned by getUnusedDfs(knowledge, empty set) which will report unused definitions in the knowledge base (we're not interested in definitions that are defined and used in the knowledge base).
Similar instantiations of method calls are needed to identify expressions that are used in the knowledge base but not defined; we can identify these by a call that does not include queries in the second argument:
- getUndefined(knowledge + beliefs + inserts (additions), empty set)
- getUndefined(knowledge + goals + adopts (additions), empty set)
Because we are also interested in reporting expressions used in queries that have not been defined, we can add queries and preconditions as well in the second argument to obtain these in one go as well:
- getUndefined(knowledge + beliefs + inserts (additions), belief queries + preconditions)
- getUndefined(knowledge + goals + adopts (additions), goal queries)
Again we need to check that we are not reporting expressions used in the knowledge base twice.
Beliefs and Goals
A very similar story as discussed above for knowledge applies for beliefs and goals as well. In fact, the calls above are symmetric in terms of knowledge and beliefs/goals and in effect do not distinguish whether a definitions in the knowledge or in the belief/goal base is not used. As we do not consider it important to be able to report the origin of a definition, i.e., whether it has been defined in the knowledge, belief or goal base, we do not need to do anything in addition.
It is interesting to alert a programmer that a goal will never be achieved, i.e., will never believed to be the case. We can check this by verifying that an initial or adopted goal can never follow from the agent's knowledge or beliefs. The following call can be used to implement this check:
- getUndefined(knowledge + beliefs + inserts (additions), goals + adopts)
From the set that is returned by this method call we should remove again the knowledge queries that are not defined.