Lists in SADL

Last revised 7/8/2021. Contact us.

Introduction

A list differs from a set in that the members of a list are in a specified order and there can be duplicate members. From a modeling perspective, this is a big difference. It is typical in many modeling languages to represent a list using a construct with two pointers: the first points to the current member of the list and the second points to a list which is the rest of the list. A typed list has further constraints to specify that members of the list must also be members of a specified class.

Definition and Examples

OWL does not have a standardized mechanism for typed lists. OWL builds on RDF which does have a list construct but an RDF list is not typed and, because of the way it is constructed, it’s use makes reasoning over a model theoretically undecidable. Because of the significant importance of lists in modeling many real-world domains, SADL provides a typed list construct defined in SadlListModel.owl, which is automatically added to the OwlModels folder of a project and automatically imported into any .sadl file (and its corresponding OWL file) that uses a SADL typed list construct. This basic construct in SadlListModel.owl is, in SADL syntax:

uri "http://sadl.org/sadllistmodel" alias sadllist.

^List is a classdescribed by ^first,
    described
by rest with values of type ^List,
    described
by lengthRestriction with values of type int,
    described
by minLengthRestriction with values of type int,
    described
by maxLengthRestriction with values of type int.


A typed list is created in a SADL ontology by referencing the type followed by the keyword List. (In the sadllist model above, the caret (^) in front of List tells the editor that this is not the SADL grammar keyword List but a user-defined concept named List.) Note that the property ^first is an RDF property, as indicated by the more florescent green color, so that the members of the list can either be instances of a class or of a data type. Since first is also a keyword in the SADL grammar it must be also preceded by a caret. Below are the declaration of two typed list classes, the first with members from the Person class and the second with members of type XSD string.

TopTenStudents is a type of Person List.

TopTenFavoriteNames is a type of string List.

In a SADL model using a typed list construct, the typed list definition creates a subclass of sadllist:List with some additional restrictions.

·         first can only have values of the specified type, e.g., Person or string in the above examples.

·         rest can only have values which belong to the class being defined, e.g., TopTenStudents or TopTenFavoiteNames; the rest property value must be of the same type as the subject.

Note that the other properties in the sadllist model (lengthRestriction, minLengthRestriction, maxLengthRestriction) are used to constrain the length of lists belonging to the defined sadllist:List subclass. For example,

ChildrenList is a type of Person List length 1-*.

creates a subclass of sadllist:List named ChildrenList and whose members can only be instances of Person and which must contain at least one element but can contain any larger number of elements. Please do not confuse a cardinality restriction on a property whose range is a subclass of sadllist:List with restrictions on the length of instances of the sadlist:List subclass. To illustrate:

ChildrenList is a type of Person List length 1-*.
children
describes Person with values of type ChildrenList.
children of Person has at most 1 value.

The first line in this example includes a list length restriction that instances of the class ChildrenList should have at least one and may have any larger number of members.
The third line in the example is a maximum cardinality restriction indicating that an instance of Person should have at most one value of the children property.

Note also that typed list classes do not have to have a name. They can be used, for example, as the range of a property. The definition of the property children above could use an unnamed typed list class.

children describes Person with values of type Person List length 1-*.

This will create an unnamed subclass of sadllist:List, and the rest property will be restricted to values of the type of this unnamed subclass of sadllist:List.

It is also possible to create instances of a SADL list class. For example,

{John, Sue, Craig} are instances of Person.

JoesChildren is the ChildrenList [John, Sue, Craig].

creates an instance of ChildrenList with ordered members John, Sue, and Craig. Similarly, we could have created an instance of an unnamed subclass of sadllist:List.

JoesChildren is the Person List [John, Sue, Craig].

Functions Operating on SADL Typed Lists

There are basically two kinds of things you can do with SADL typed lists.

  1. You can declare typed list classes (subclasses of sadllist:List) and instances of those classes, as illustrated above.
  2. You can reference the lists or elements of the lists in rules and queries.

The SADL grammar provides expressions for referencing members of a typed list. These expressions can be used in rules and queries and result in functions in the SADL intermediate form. If the active translator can translate these functions into built-in functions in the target rule or query language, then the reasoner/rule engine/query engine can do what the grammar instructs.

The SADL grammar constructs include the following, where l1 is a SADL typed list and el1 is an instance of the type of the list.

  1. element before el1 in l1    // translates to a function that returns the element in l1 that is before el1, if it exists
  2. element after el1 in l1     // translates to a function that returns the element in l1 that is after el1, if it exists
  3. first element of l1         // translates to a function that returns the first element in l1, if it exists
  4. last element of l1          // translates to a function that returns the last element in l1, if it exists
  5. element 2 of l1             // translates to a function that returns the 2nd element in l1, if it exists (the first position in the list is 0)
  6. index of el1 in l1          // translates to a function that returns the index of element el1 in l1, if it exists
  7. length of l1                     // translates to a function that returns the length of l1

 These SADL grammar constructs are equivalent, when using the Jena-based reasoner/translator pair, to the following SADL constructs, respectively, using the Jena-based built-in functions directly.

  1. elementBefore(l1, el1)
  2. elementAfter(l1, el1)
  3. firstElement(l1)
  4. lastElement(l1)
  5. elementInList(l1, 2)
  6. ^index(l1, el1)
  7. listLength(l1)

Note that in the above references, the caret before the index and length built-in function names is necessary because the names are also keywords in the SADL grammar.

Besides the grammar constructs and associated built-in functions above, the Jena-based default reasoner/translator pair support the following built-in functions for SADL typed lists.
  1. insertElementInList(l1, el13)   // function that returns a new list of the same type as l1 but with additional element el1 at index 3 (the first position in the list is 0)
  2. deleteElementFromList(l1, 1)      // function that returns a new list of the same type as l1 but with the element at index 1 removed (the first position in the list is 0)
  3. isListHead(l1)                    // function that returns true if the list l1 is not the value of any triple with "rest" as predicate
  4. sadlListToString(l1)              // function that returns a serialization of the list l1 as a string in the SADL syntax used to declare instances of typed lists

The third Jena built-in function which may be found useful in rules dealing with SADL typed lists. Because a list with more than one element is actually a sequence of lists, when using the various list operations discussed above or on other occasions it may be desirable to only operate on the first list in such a series. For example, given this model

l1 is the YooHooList [yh1, yh2, yh3, yh4].

and this rule

Rule PrintList: if x is a YooHooList and l is length of x then print(x, sadlListToString(x), " length = ", l).

inference will produce these results.

print: <http://sadl.org/UsingListExpression.sadl#l1> [yh1, yh2, yh3, yh4] length = 4
print: b6cb453b-6297-4cac-bd8d-a6ac96916364 [yh2, yh3, yh4] length = 3
print: c55e02b2-8968-4d19-8962-38f04d0fc800 [yh3, yh4] length = 2
print: afbbc8b7-0d10-47ac-82bc-845bff14c63e [yh4] length = 1

However, if the rule is modified  as follows

Rule PrintList: if x is a YooHooList and isListHead(x) and l is length of x then print(x, sadlListToString(x), " length = ", l).

these results, which may be more what is intended when using the length built-in, are produced.

print: <http://sadl.org/UsingListExpression.sadl#l1> [yh1, yh2, yh3, yh4] length = 4

The fourth Jena built-in function may be useful, when the results are passed into the print built-in function, for debugging rules.

Empty Lists

Besides having constraints on the type of members and the length of lists, SADL typed lists differ from RDF lists (rdf:List) in another important way. RDF has a special instance of rdf:List named rdf:nil, which is the empty list--a list without any members. Furthermore, every rdf:List is terminated by a triple with predicate and value rdf:rest rdf:nil. This is deemed unnecessary and undesirable in SADL typed lists, which simply terminate a list with an instance of the typed list that is not the subject of a sadllist:rest property.

However, an empty list  instance of a SADL typed list  class can occur. That such is necessary may be illustrated by asking what the function in the second line below should return given the definition of l3 in the first line.

l3 is the YooHooList [yh1].

deleteElementFromList(l3, 0)

In fact, an instance of an empty SADL typed list can even be declared in the grammar, either using a named sadllist:List subclass or an unnamed one.

ChildlessChildren1 is the Person List [].

ChildlessChildren2 is the ChildrenList [].

Appendix A: A SADL Typed List Declaration and Instance in OWL RDF-XML Syntax

In RDF-XML syntax, the following is the declaration of a SADL typed list generated from the SADL

ChildrenList is a type of Person List length 1-*.

  <owl:Class rdf:ID="ChildrenList">
    <rdfs:subClassOf>
      <owl:Restriction>
        <owl:hasValue rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
        >1</owl:hasValue>
        <owl:onProperty rdf:resource="sadllistmodel#minLengthRestriction"/>
      </owl:Restriction>
    </rdfs:subClassOf>
    <rdfs:subClassOf>
      <owl:Restriction>
        <owl:allValuesFrom rdf:resource="#ChildrenList"/>
        <owl:onProperty rdf:resource="sadllistmodel#rest"/>
      </owl:Restriction>
    </rdfs:subClassOf>
    <rdfs:subClassOf>
      <owl:Restriction>
        <owl:allValuesFrom rdf:resource="#Person"/>
        <owl:onProperty rdf:resource="sadllistmodel#first"/>
      </owl:Restriction>
    </rdfs:subClassOf>
    <rdfs:subClassOf rdf:resource="sadllistmodel#List"/>
  </owl:Class>

In RDF-XML syntax, the following is the declaration of the instance of a SADL typed list generated from the SADL

JoesChildren is the ChildrenList [John, Sue, Craig].

  <sadllistmodeltemplate:ChildrenList rdf:ID="JoesChildren">
    <sadllistmodel:rest>
      <sadllistmodeltemplate:ChildrenList>
        <sadllistmodel:rest>
          <sadllistmodeltemplate:ChildrenList>
            <sadllistmodel:first rdf:resource="#Craig"/>
          </sadllistmodeltemplate:ChildrenList>
        </sadllistmodel:rest>
        <sadllistmodel:first rdf:resource="#Sue"/>
      </sadllistmodeltemplate:ChildrenList>
    </sadllistmodel:rest>
    <sadllistmodel:first rdf:resource="#John"/>
  </sadllistmodeltemplate:ChildrenList>


 If the SADL typed list class is unnamed, as in this declaration of the instance of a SADL typed list, the generated RDF-XML is slightly different.

JoesChildren is the Person List [John, Sue, Craig].

  <rdf:Description rdf:ID="JoesChildren">
    <sadllistmodel:rest rdf:parseType="Resource">
      <sadllistmodel:rest rdf:parseType="Resource">
        <sadllistmodel:first>
          <sadllistmodeltemplate:Person rdf:ID="Craig"/>
        </sadllistmodel:first>
        <rdf:type rdf:nodeID="A1"/>
      </sadllistmodel:rest>
      <sadllistmodel:first>
        <sadllistmodeltemplate:Person rdf:ID="Sue"/>
      </sadllistmodel:first>
      <rdf:type rdf:nodeID="A1"/>
    </sadllistmodel:rest>
    <sadllistmodel:first>
      <sadllistmodeltemplate:Person rdf:ID="John"/>
    </sadllistmodel:first>
    <rdf:type rdf:nodeID="A1"/>
  </rdf:Description>

  <owl:Class rdf:nodeID="A1">
    <rdfs:subClassOf>
      <owl:Restriction>
        <owl:hasValue rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
        >1</owl:hasValue>
        <owl:onProperty rdf:resource="sadllistmodel#minLengthRestriction"/>
      </owl:Restriction>
    </rdfs:subClassOf>
    <rdfs:subClassOf>
      <owl:Restriction>
        <owl:allValuesFrom rdf:nodeID="A1"/>
        <owl:onProperty rdf:resource="sadllistmodel#rest"/>
      </owl:Restriction>
    </rdfs:subClassOf>
    <rdfs:subClassOf>
      <owl:Restriction>
        <owl:allValuesFrom rdf:resource="#Person"/>
        <owl:onProperty rdf:resource="sadllistmodel#first"/>
      </owl:Restriction>
    </rdfs:subClassOf>
    <rdfs:subClassOf rdf:resource="sadllistmodel#List"/>
  </owl:Class>