This is essentially about bringing OWL reasoning into running applications. To achieve so in full, we need addressing the dynamic nature of application data, i.e. creating dynamic ontologies and integrating them into conventional programming languages. So, we need to look at how the procedural programming languages can be ontologically represented.
You can think about any ontology as an instant snapshot of the real or virtual world, depending on what you modelling. You cannot assert contradictory facts in an ontology because OWL is monotonic. When the world changes, you need another instance of your ontology, which models the new world. This is the obvious approach to deal with dynamic ontologies.
Any procedural programming language has three basic control structures: execution sequence, decision (if-then-else or case statements), and repetition. Our goal is to represent these structures in OWL-DL, which is an entirely declarative (non-procedural) language. However while we can easily program an infinite loop in a procedural language, it is impossible in OWL-DL, which is tractable: any reasoning query in OWL-DL is resolved in a finite time. Also destructive assignment (when a new value is assigned to a variable, and the old value is destructed) is normal in procedural languages, but impossible in OWL-DL, where values of properties, and SWRL variables cannot be destructed. So, because of the fundamental difference between procedural and declarative languages, it is impossible to achieve our goal, unless we use some procedural meta-programming mechanism. For this purpose we introduce a procedural execution environment, which operates on ontological structures.
The execution sequence is modelled through the OWL module import. There are two special cases: with or without the destructive assignment.
For illustration purposes, here we use C language as a concrete syntax for a procedural language. The following execution sequence:
A(); B(); C(); … Z();
is represented as a sequence of OWL dynamic module instantiations and imports:
Here A, B, C, … Z are procedures or functions with optional parameters. Each procedure or function can be very simple, or as complex as an application, including: user interface, instantiation of the OWL module, starting a reasoner on it, and multiple DL queries. In this project, the DL query language and associated Manchester syntax are essential, as we tend to encode almost all application logics in those languages.
Thus this diagram represents the following execution sequence:
-- instantiate OWL module A;
-- optionally run a reasoner, and DL queries on it;
-- instantiate OWL module B, importing module A;
-- optionally run a reasoner, and DL queries on it;
-- instantiate OWL module C, importing module B;
-- optionally run a reasoner, and DL queries on it;
-- so on.
A destructive assignment is modelled as OWL module instantiation and retraction. For example, a code:
int i;
A();
i = 0;
B(i);
i = 1;
C(i);
is represented as the following ontology transformation. (We describe the ontologies in a simplified Manchester syntax. A full example can be found in the project code repository at /OWL/examples/destructive_assignment.)
Ontology: <A>
Datatype: xsd:int
DataProperty: i
Characteristics:
Functional
Range:
xsd:int
Individual: program
Ontology: <B>
Import: <A>
Individual: A:program
Facts: A:i 0
Ontology: <C>
Import: <A>
Individual: A:program
Facts: A:i 1
A binary decision is modelled as an instantiation of one of two OWL modules.
For example, consider the following program:
A();
if (condition)
then B();
else C();
This program is represented as the following ontology transformation:
The condition can be any binary condition, which is asserted or inferred in ontology A, for example, an individual belonging or not belonging to a class, a consistent or inconsistent class, etc. The execution environment (an ontology transformation engine) should recognise the condition and instantiate the appropriate module (A or B).
A multiple choice is a generalisation of the binary decision.
Let us consider a following program:
A();
switch (condition)
{
case b:
B();
break;
case c:
C();
break;
default:
D();
}
This program is mapped to the following ontology transformation:
The repetition is modelled as consecutive instantiations and retractions of OWL modules.
For example, consider the following program:
observer();
while (1)
update();
Here the observer module contains the logic to observe some process. After starting-up the observer becomes resident in the system. The update module is called in the endless loop and notifies the observer on fresh data from the observable process.
The correspondent ontology transformation is the following:
You can implement this pattern in Protégé desktop application:
1. Create your observer ontology;
2. Create your update ontology importing your observer ontology;
3. Load the update ontology into Protégé;
4. Change the update ontology file from outside of Protégé;
5. Protégé will ask you whether you want to reload the ontology; agree to reload;
6. Repeat from step 4.