Equations, also known as functions (see Foundational Concepts in Semantic Modeling, Part 2), are snippets of procedural code that provide instructions for computing an output from a set of inputs. At the declaration, or definition level, inputs are typed variables. At execution time, inputs are actual values passed in to the function. In the function declaration, an output is unnamed but its type is defined as the return type of the function. Actually, in the general case a function can return multiple values, as functions can in Python. Functions can be very important in modeling a domain. For example, many reasoners allow rules to have built-in functions to handle math operations, and without the ability to do math operations it may not be possible to construct a useful model.
The SADL grammar supports two kinds of equations, one in which the body of the function (the set of instructions for computing the function output) is defined in the SADL statement, and another where the body of the function exists somewhere outside of the ontology. The first kind uses the Equation grammar keyword.
Equation areaOfCircle (float radius) returns float: PI*radius^2 .
Equation volumeOfCylinder (float radius, float height) returns float: areaOfCircle(radius) * height.
As the example illustrates, one Equation may use another in its body. Here the volumeOfCylinder Equation uses areaOfCircle in its body.
The second kind of equation uses the External grammar keyword. This kind of equation provides a name and signature, but the actual specification of the body of the equation (the computational instructions) is located elsewhere. This gives rise to at least two and as many as three resource identifiers.
External abs (float x) returns float:
"java.lang.Math.abs"
located at "http://java.lang.Math".
Note: in the example above, the external identity URI is not a conformant URI, but rather is the Java package, class, and method name of the external Java method to which the equation maps. For information on how to wrap any Java class method that takes primitive data as inputs and and returns a primitive data type output in a SADL External statement to make it available for use in reasoning, see Wrapping Java Class Methods for the Jena Reasoner.
The examples in the previous section are all user-defined equations. Such user-defined equations may or may not be executable during reasoning, depending upon the reasoner/translator pair chosen and their ability to invoke the function. Reasoner/translator pairs may also have a known set of functions which can be used in models. These are defined as external equations in the SadlBuiltinFunctions.sadl model in the project's ImplicitModel folder. These functions will normally be more tightly integrated with the reasoner that user-defined functions, as is the case with Jena built-ins, or they may be functions native to the language as is the case with the SWI-Prolog reasoner. The content of the SadlBuiltinFunctions.sadl model is obtained from the reasoner/translator pair itself. Generally speaking, built-in functions in the SadlBuiltinFunctions.sadl model, even if implemented in Java, will not conform to the access mechanism described above and illustrated with java.lang.Math.abs. For example, built-in functions for the Jena Reasoner are implemented by a class, not a single method, and take Jena class instances as inputs rather than primitive data types.
While named functions declared with either the Equation or External keyword can be used in expressions in SADL or derivative grammars, using the functions to do actual computation is a task for the reasoner or other related processors.
The name of the equation and the type of inputs allowed and the type of output generated is specified in the equation's signature. This information is useful for type checking during model construction. The format of the signature is the name, followed by an opening parenthesis, followed by the type and name of the each argument, each type/name pair separated by a comma, followed by a closing parenthesis, followed by the types of the returned values, comma separated if more than one. The syntax is shown below, where the angle brackets enclose a grammar conforming type or name but are not part of the syntax.
<name>(<type of 1st argument> <name of first argument>, <type of second argument> <name of second argument>....)<type of first returned value>, <type of second returned value>...
The examples above provide concrete illustrations of signatures.
There are some special notations available for use in signatures. The most vague ambiguous type symbol is the unknown indicator, "--", which is used without a name.
External foo (--) returns -- : "http://entirely/vague#foo".
This tells us that we do not know what kind of inputs foo accepts or what kind of outputs should be generated. This does not mean that we can't reference the function, only that we know nothing that will allow us to do type checking while building the model.
An ellipsis (...) is used to indicate a variable number of arguments. An ellipsis may be typed or untyped. A typed ellipsis is preceded by the type of the inputs that are expected. An ellipsis does not have an associated name.
External formatString(string fmt, float ... vals) returns string : "java.lang.String.format".
This tells us that the formatString function takes a string as the first argument, named "fmt", followed by any number of float inputs, and returns a string as output.
External print(...) returns --: "com.ge.research.sadl.jena.reasoner.builtin.Print".
This signature tells us that the print function can take any number of inputs of unspecified type and what it will return is not known.
Some built-in functions may allow inputs which are of type List (see Lists in SADL) or of type UnittedQuantity (see UnittedQuantities in SADL). In order to be able to properly do type checking, built-in functions should be able to tell the reasoner/translator pair whether such inputs are allowed. This information is in addition to the argument and return type information contained in the equation signature. The following rules describe how arguments types interact with list and unitted quantity support.
The SADL grammar supports additional information about function arguments and return types. There is support for three special cases.
External sadlListToString(--) returns string: "com.naturalsemantics.sadl.jena.reasoner.builtin#sadlListToString".
External formatString<(string fmt, ...)
returns string: "java.lang.String.format".
// The first argument is a string,
followed by any number of arguments of any type.
External strConcat(string str1, string ...
moreStrs)
returns string: "org.apache.jena.reasoner.rulesys.builtins#strConcat".
// The first argument is a string,
followed by any number of arguments of type string.
While these could be combined, as in this example of a method that takes any type of first argument followed by any number of additional arguments of any type, care should be taken to match the use of special types with what the underlying function actually expects.
External print(--, ...) returns --: "com.ge.research.sadl.jena.reasoner.builtin#print".
Translation of equations and external equations to OWL uses the
meta-model defined in the SADL Implicit Model. Excluding augmented
types, the meta-model is the following.
Language is
a class.
{Java, Python,
Text, OtherLanguage}
are instances
of Language.
Script is
a class,
described by
language
with a
single value
of type
Language,
described by
script
with a
single value
of type
string.
^Equation
is a
class,
described by
expression
with values
of type
Script.
arguments describes
^Equation
with a
single value
of type
DataDescriptor
List.
returnTypes describes
^Equation
with a
single value
of type
DataDescriptor
List.
localDescriptorName of DataDescriptor has at most 1 value.
dataType of DataDescriptor has at most 1 value.The variables which are arguments of an equation have an explicit order which must be preserved in the OWL representation. Therefore the arguments of an equation are a list in order to make the order explicit--in this case a DataDescriptor List. The same is true of returnedTypes as it is possible that more than one value will be returned by equations in some languages. The scope of a variable in an equation is limited to that equation. Two equations in a SADL model (which corresponds to an XML namespace by SADL design) might have argument variables with the same name but they are distinct, unrelated variable instances. Therefore, in the OWL representation we cannot just use the variable name as it appears in the signature as the unique identifier of the variable since the scope of the name can be no more narrow than the current namespace. However, since equation names must be unique within a SADL model, we can create unique identifiers by concatenating the variable name with the equation name. This concatenated name becomes the local name of the value of the descriptorVarible property of instances of the DataDescriptor class. The actual name as it appears in the equation signature is preserved as the value of localDescriptorName. An instance of a GPVariable (definition not shown in the meta-model above, see augmented types) is created and given the unique URI constructed from the namespace URI and the concatenation of the equation localname and the argument local name.
Use of this meta-model is illustrated by the following OWL snippet showing the translation of the areaOfCircle equation above.
Observe that the sadlimplicitmodel:arguments and sadlimplicitmodel:returnTypes properties have values of type _:b0, a subclass of the sadllistmodel:List. Each element of these lists is an instance of a sadlimplicitmodel:DataDescriptor, which captures the variable local and model name, for the argument, and the type, xsd:float, for both the argument and returned value.
The translation of the external equation abs provides a second example.
In this case there is no expression with a language
and script but instead there is an externalURI
(identity of the equation) and an externalURL (where to find the
equation).
See also: