Rule Built-ins

Last revised 7/8/2021. Contact us.

Introduction

Rules are a convenient way to capture domain knowledge in the familiar format of "if this then that". Many of a rule's conditions and conclusions will contain graph patterns, but sometimes built-in functions will be used. Consider the following SADL rule.

    Rule AreaOfRectangle 
        
given        x is any Rectangle
        then          
 area of x= height of x* width of x.

This rule expands into a number of conditions and a single conclusion. There is one explicit variable in the rule, x, but the expansion will create additional implicit variables. This rule will translate into something like the following for most reasoners, where a "?" is placed in front of variable names to identify them as variables.

if
  ?x rdf:type Rectangle
  ?x height ?v1
  ?x width ?v2
  product(?v1,?v2,?v3)
then
  ?x area ?v3

When variables are used in multiple graph patterns, as they are in this example, the first occurrence in the rule conditions "binds" the variable and those bindings are then be used in subsequent conditions and in the conclusions. In this example, x is bound to instances of the class Rectangle. Each possible binding will result in the rule being evaluated by the reasoner.

All of the conditions and the conclusion are graph patterns except "product(?v1,?v2,?v3)". This condition is a built-in function. Functions in a rule's conditions return true (meaning the condition is satisfied) or false (meaning the condition is not satisfied so the rule should not "fire" (cause the conclusions to be processed). In this case, the function also binds the result of the procedural computation (multiplication) to a new variable, ?v3.

Special Note for Jena Reasoner

Note: if a Jena rule has no triple patterns in the rule body (conditions), the Jena reasoner will treat it as an axiom and will not provide the current model to the condition built-ins. This means that any built-in used in a rule body without triple patterns will not be able to get any ontological information. If necessary, a pseudo triple pattern can be placed in the rule body to force the ontology to be available within the built-in.

Jena Reasoner Built-ins

The default reasoner for SADL Version 3 is the Jena general purpose rule engine. This reasoner comes with a number of built-in functions, referred to in the Jena documentation as "Builtin primitives". These built-in functions are all programmed in the Java language.

When using Jena-provided built-ins, it is important to understand the difference between the Jena syntax (see "Built-in Primitives" at http://jena.apache.org/documentation/inference/#RULEbuiltins ) and the SADL syntax. In the actual Jena rule created from the SADL rule, which is what is shown in the Jena documentation at the link above, if an assignment of the result is made to a variable, that variable will be the last argument to the actual built-in. This is illustrated in the expanded rule in the example above. In SADL syntax, the assignment is shown explicitly to be the variable on the left of the "=" or "is" assignment or implicitly as a nesting of terms. This is illustrated below for the sum built-in:

Note that if built-ins combine operations they can hide important dependencies from the Jena Rule Engine. For example, if one built-in creates a structure (a set of triples) and another uses the structure, the Rule Engine may not detect that the structure must be built by one rule or set of rules before it can be used by another. The solution to this problem is to always work with the individual elements, not with larger structures.

Tables of Jena Built-Ins Available in SADL Version 3 are shown below. To make the table more readable, only the class name is shown. However, in registration references the entire fully-qualified class name must be specified.

Built-in Functions in the package com.ge.research.sadl.jena.reasoner.builtin.

The package name for all of these is com.ge.research.sadl.jena.reasoner.builtin.

Built-in, SADL Rule Syntax Java Implementation Class Purpose
y is abs(x) Abs Return the absolute value of the numerical value x
y is acos(x) Acos Return the inverse cosine of the numerical value x (return value in radians)
y is asin(x) Asin Return the inverse sine of the numerical value x (return value in radians)
y is 3.4 Assign Used in translation  of assignment of a literal to a variable in a rule body
y is atan(x) Atan Return the inverse tangent of the numerical value x (return value in radians)
z is average(x,y, ...) Average Return the average of any number of numerical values
y is ceiling(x) Ceiling Return the smallest integer larger than x
y is cos(x) Cos Return the cosine of the numerical value x representing an angle in radians
(1): n is countMatches(s, p)
         or
      n is countMatches(s, p, x)
(2): n is countMatches(s1, p1, o1, s2, p2, o2, ..., sn, pn)
         or
      n is countMatches(s1, p1, o1, s2, p2, o2, ..., sn, pn, x)
CountMatches This built-in returns the same value as "listLength(list(...))" for the same arguments; it counts the number of  matches to the graph pattern specified in the arguments. This built-in does not create an rdf:List so there are no additions to the inferred model as a side-effect. See the "list" built-in below for a detailed discussion of the arguments. See also "countUniqueMatches".
n is countUniqueMatches(....) CountUniqueMatches Counts the number of unique matches (duplicates removed); same argument pattern as CountMatches
y is floor(x) Floor Return the largest integer smaller than x

y is getInstance(cls)
y is getInstance(cls, c1a, c1b, c2a, c2b, ..., cna, cnb)
y is getInstance(cls, c1a, c1b, c2a, c2b, ..., cna, cnb, true)

GetInstance Return the instance of the class cls which also matches the set of constraints specified by {c1a, c1b, c2a, c2b, ..., cna, cnb}. Each pair of constraints represents either a triple pattern for which the matching instance is the subject, e.g., (?, c1a, c1b) and hence c1a is a property, or a triple pattern for which the matching instance is the object value, e.g., (c1a, c1b, ?) and hence c1a is an instance and c1b is a property. If no match exists create an instance of type cls and instantiate triples for all of the constraints. (A subsequent call with the same arguments will then return the new instance.) If there is a last boolean argument whose value is true, the new instance will always be created, matching the constraints, even if a match already exists.
Note: getInstance is deprecated and should not be used. The intended purpose is much better achieved by thereExists,  see ThereExists below.
greaterThan(x,y)
  or
x > y
GreaterThan This extends the Jena GreaterThan built-in by a) adding string comparison so that ordering of URI's can be acheived, and b) allowing a returned boolean value to be bound to a variable ("bval is greaterThan(x,y)"). Note that the latter only works with the explicit form of the built-in, not with the "x > y" representation.
lessThan(x,y)
  or
x < y
LessThan This extends the Jena LessThan built-in by a) adding string comparison so that ordering of URI's can be acheived, and b) allowing a returned boolean value to be bound to a variable ("bval is lessThan(x,y)"). Note that the latter only works with the explicit form of the built-in, not with the "x < y" representation.
(1): lst is list(s, p)

       or

      lst is list(s, p, x)

(2): lst is list(s1, p1, o1, s2, p2, o2, ..., sn, pn)

        or

       lst is list(s1, p1, o1, s2, p2, o2, ..., sn, pn, x)

(3): lst is list(lit1, lit2, lit3, ....)

List This built-in returns an rdf:List instance whose contents is determined by the arguments. There are three forms as shown in the first column. The first two forms specify graph patterns with one unbound variable node (implicit or explicit) that are to be matched to create the list. Form (1) identifies a graph node anchor or subject as the first argument and a graph edge or property as the second argument. A free (unbound) variable may be specified as the 3rd argument but is implied if not explicit--the list is the possible bindings of this variable. Form (2) is an extension of form (1) and has a series of subject-predicate-object specifications in triple patterns. The subject of a subsequent triple pattern can be the object of a previous pattern, or any other combination as long as the triple patterns are related in some way. The unbound variable, whose bindings will constitute the list, is the last argument, either implicit or explicit. Form (3) creates a list of all of the arguments when they are all literal values or individuals. (Note that the actual test is not property and not class.)

Note that this built-in will return duplicate list items if the occur. To remove duplicate items from a list use the "unique" built-in.

list3 is listConcat(list1, list2) ListConcat This built-in is for use in a rule premise and concatenates two lists together to form a new list.
lst is listSubtract(list1, list2) ListSubtract Remove all members of list2 from list1, if they are in list1, and return what remains.
str is listToString(lst) ListToString Converts a list to a string representation of the list
ln is localname(concept) Localname Where concept is an rdf:Resource with a URI, return the local name
y is max(x1, x2, ...)
y is max(lst)
y is max(s1,p1,o1,s2,p2,o2,...)
Max Return the minimum of any number of arguments, each of which must be a numerical value.  Can take a single argument of type rdf:List. Can also take a graph pattern (3rd example) as input, see notes after this table.
y is min(x1, x2, ...)
y is min(lst)
y is min(s1,p1,o1,s2,p2,o2,...)
Min Return the minimum of any number of arguments, each of which must be a numerical value. Can take a single argument of type rdf:List. Can also take a graph pattern (3rd example) as input, see notes after this table.
z is mod(x,y) Mod Return the value of x mod y
noSubjectsOtherThan(s, p, o) NoSubjectsOtherThan Given three arguments, s, p, and o, which identify a triple pattern, return true (premise matches) if and only if the model contains the specified triple but does not contain any other triples with the same predicate and object
notOnlyValue(s, p, o) NotOnlyValue Returns true if there is at least one triple with subject s, property p, and value o but there is also at least one triple with subject s, property p, and a value other than o.
noUnknownValues(s, op, p2) NoUnknownValues For the given subject s, if all values of the object property op have at least one value of the property p2, return true. Otherwise return false.
noValue(s, p)
noValue(s, p, o)
noValue(s, p1, p2, p3, ..., pn)
noValue(s, p1, p2, p3, ..., pn, o)
noValue(s1,p1,o1,s2,p2,o2,...)
NoValue 1) Subject s has no property p. 2) Subject s does not have property p with value o. 3) Starting at node s, there is no set of triples with edges p1, p2, .. , pn that leads to one or more values. 4) Starting at node s, there is no set of triples with edges p1, p2, ...,pn that lead to a value o. 5) The triple pattern expressed by the arguments (see notes below table) does not exist in the graph.
noValuesOtherThan(s, p, o) NoValuesOtherThan Given three arguments, s, p, and o, which identify a triple pattern, return true (premise matches) if and only if the model contains the specified triple but does not contain any other triples with the same subject and predicate
oneOf(x, val1, val2, ...)
OneOf In the Jena a rule cannot have a disjunction. The oneOf built-in enables one kind of disjunction by returning true if the first argument matches any of the subsequent arguments, either by URI for instances and classes, or by string matching for literals. Otherwise it returns false. The first argument is normally a bound variable, which could be a class to which something belongs or the value of a property, and the subsequent arguments are the values for which the rule should fire. Note that oneOf only returns true or false to allow or disallow rule firing. It does not bind a value to an output variable. Without oneOf, a rule would have to be written for each matching argument.
y is pow(x1, x2) Pow Return the result of raising the first argument, which must be a numerical value to the second, which must also be a numerical value
print("hi there ", x) Print Like the Jena print built-in, but overrides it to output to stdout. For the IDE, this will be the console window.
y is product(x1, x2, ...)
y is product(lst)
y is product(s1,p1,o1,s2,p2,o2,...)
Product For 2 or more arguments, return the product of the arguments, all of which must be numerical values. Alternatively, a single argument is an rdf:List of numerical values which are multiplied together to determine the return value. Can also take a graph pattern (3rd example) as input, see notes after this table.
y is sin(x) Sin Return the sine of the numerical value x representing an angle in radians
y is sqrt(x) Sqrt Return the square root of a number x
x is strafter(str, delim)
StrAfter The string str is split using the Java String split method on the delimiter delim and portion of str that is found after delim is returned.
x is strbefore(str, delim) StrBefore The string str is split using the Java String split method on the delimiter delim and portion of str that is found before delim is returned.
y is subtractDates(x1, x2, x3) SubtractDates The first argument must be an xsd DateTime. The second argument may be (a) an xsd DateTime, in which case the difference between the first and second arguments is computed, or it may be (b) a number, in which case its value is subtracted from the first argument. The third argument is a string which must begin with one of "y" (year), "mo" (month), "d" (day), "mi" (minute), "h" (hour), or "s (second). If the second argument is an xsd DateTime (a), the difference is converted to a number with the units specified by the third argument. If the second argument is a number (b), then the third argument is taken to be the units of this number. The calculated value, which will be (a) a number, or (b) an xsd DateTime, is returned.
y is sum(x1, x2, ...)
y is sum(lst)
y is sum(s1,p1,o1,s2,p2,o2,...)
Sum For 2 or more arguments, return the sum of the arguments, all of which must be numerical values. Alternatively, a single argument is an rdf:List of numerical values which are summed to determine the return value. Can also take a graph pattern (3rd example) as input, see notes after this table.
y is tan(x) Tan Return the tangent of the numerical value x representing an angle in radians
then there exists a Velocity and the Velocity has ^value sosair and the Velocity has unit vunit plus speedOfSound of air is the Velocity
    or
...then thereExists(Velocity, ^value, sosair, unit, "m/sec", Plus, air, speedOfSound)     
ThereExists Only a rule conclusion can contain thereExists so the built-in is never executed unless the rule fires. The first argument identifies the class of the instance to be found. Subsequent argument pairs identify the necessary triples that must contain an instance for it to match. After the Plus argument, additional triples patterns may be specified to create additional (non-key) triples. For a more thorough discussion with examples, see There Exists.
lst2 is unique(lst1) Unique Takes an rdf:List instance as input and removes any duplicate list items, returning the resulting list. If there are no duplicates the original list is returned.

Several of these built-ins have special syntax in SADL. These include the following.

  1. NoValue (Jena built-in): p of x is unknown, p of x is not v
  2. NoValuesOtherThan: p of x is only y
  3. NotOnlyValue: p of x is not only y

Built-in Functions in the package com.naturalsemantics.sadl.jena.reasoner.builtin.

There are several built-in functions supporting SADL typed lists. The package name for these is com.naturalsemantics.sadl.jena.reasoner.builtin.

Built-in, SADL Rule Syntax Java Implementation Class Purpose
newList is deleteElementFromList(existingList, idx) DeleteElementFromList Create and return a new list which is a duplicate of the original list minus the idxth element. Returns false (rule will not fire) if the element is not found.
element2 is elementAfter(existingList, element1) ElementAfter Find and return the element in the existing list after the specified element. Return false (rule will not fire) if the element is not found.
element1 is elementBefore(existingList, element2) ElementBefore Find and return the element in the existing list before the specified element. Return false (rule will not fire) if the element is not found.
element is elementInList(existingList, idx) ElementInList Find and return the idxth element in the existing list. Return false (rule will not fire) if there is index is not in the range of the length of the list.
element is firstElement(existingList) FirstElement Return the first element of the existing list. Return false (rule will not fire) if the existing list is empty.
idx is index(existingList, element) Index Return the index of the specified element in the existing list. Return false (rule will not fire) if the element is not found in the list.
newList is insertElementInList(existingList, element, idx) InsertElementInList Create and return a new list which is a duplicate of the original list plus the specified element inserted in the idxth location in the list.
isListHead(existingList) isListHead Check if the existing list is the head of a list, that is it is not the value of the rest property of another list.
element is lastElement(existingList) LastElement Return the last element of the existing list. Return false (rule will not fire) if the existing list is empty.
length is listLength(existingList) ListLength Return the length of the existing list. Return false (rule will not fire) only if the list does not exist.
str is sadlListToString(existingList) SadlListToString Translate the existing list into a string representation of the list in SADL syntax.

For additional documentation on these list built-in functions, and to see the SADL grammar syntax available for many of them, see Lists in SADL.