SWRLLanguageFAQ

Martin O'Connor edited this page Mar 12, 2018 · 30 revisions

The Semantic Web Rule Language (SWRL) is an expressive OWL-based rule language. SWRL allows users to write rules that can be expressed in terms of OWL concepts to provide more powerful deductive reasoning capabilities than OWL alone. Semantically, SWRL is built on the same description logic foundation as OWL and provides similar strong formal guarantees when performing inference.

This FAQ assumes that the reader is already familiar with OWL. A good introduction to OWL can be found here. This FAQ uses the presentation syntax that is supported by the SWRLAPI. This syntax is described here. Other SWRL implementations may chose an alternative presentation syntax.

A tutorial describing how to use Protégé's SWRLTab Plugin to work with SWRL rules can be found here. A Powerpoint-based overview of SWRL can be found here.

Table of Contents

What does a SWRL Rule look like?

A SWRL rule contains an antecedent part, which is referred to as the body, and a consequent part, which is referred to as the head.

Both the body and head consist of positive conjunctions of atoms:

atom ^ atom .... -> atom ^ atom

Informally, a SWRL rule may be read as meaning that if all the atoms in the antecedent are true then all atoms in the consequent must also be true.

SWRL does not support negated atoms or disjunction.

An atom is an expression of the form:

p(arg1, arg2, ... argn)

where p is a predicate symbol and arg1, arg2, ..., argn are the terms or arguments of the expression.

In SWRL, five types of predicate are supported: OWL classes, OWL properties, data types, data ranges, and built-ins.

Arguments can be OWL individuals or data values or variables referring to them.

All variables in SWRL are treated as universally quantified, with their scope limited to a given rule.

How many Atom Types are provided by SWRL?

SWRL provides seven types of atoms:

  • Class Atoms
  • Individual Property atoms
  • Data Valued Property atoms
  • Different Individuals atoms
  • Same Individual atoms
  • Built-in atoms
  • Data Range atoms

What is a Class Atom?

A class atom consists of an OWL named class or class expression and a single argument representing an OWL individual. Examples include:

    Person(?p)
    Man(Fred)

Here, Person and Man are OWL named classes, ?p is a variable representing an OWL individual, and Fred is the name of an OWL individual.

A simple example rule using class atoms to declare that all individual of type Man are also or type Person can be written:

    Man(?p) -> Person(?p)

Of course, this statement can also be made directly in OWL.

What is an Individual Property Atom?

An individual property atom consists of an OWL object property and two arguments representing OWL individuals. Examples include:

    hasBrother(?x, ?y)
    hasSibling(Fred, ?y)

Here, hasBrother and hasSibling are OWL object properties, ?x and ?y are variables representing OWL individuals, and Fred is the name of an OWL individual.

An example SWRL rule expressing that a person with a male sibling has a brother would thus require capturing the concepts of person, female, sibling of and brother of in OWL. Intuitively, the concept of person and male can be captured using an OWL class called Person with a subclass Man; the sibling and brother relationships can be expressed using OWL object properties hasSibling and hasBrother with a domain and range of Person. The rule in SWRL would then be:

    Person(?p) ^ hasSibling(?p, ?s) ^ Man(?s) -> hasBrother(?p,?s)

This rules associates the hasBrother property with all OWL individuals with one or more male siblings and assigning its value to those siblings.

What is a Data Valued Property Atom?

A data valued property atom consists of an OWL data property and two arguments, with the first representing an OWL individual, and the second a data value. Examples include:

    hasAge(?x, ?age)
    hasHeight(Fred, ?h)
    hasAge(?x, 232)
    hasName(?x, "Fred")

Here, hasHeight, hasAge, and hasName are OWL data properties, ?x is a variable representing an OWL individual, Fred is the name of an OWL individual, and ?h and ?age are variables representing data values.

Using a boolean data valued property, a rule that asserts that all persons that own a car should be classified as drivers can then be written as:

    Person(?p) ^ hasCar(?p, true) -> Driver(?p)

This rule classifies all car-owner individuals of type Person to also be members of the class Driver.

Named individuals in an ontology can also be referred to directly. For example, one could rewrite the above rule to classify an individual named Fred as a driver as follows:

    Person(Fred) ^ hasCar(Fred, true) -> Driver(Fred)

It is important to note that this rule works with a known individual called Fred in an ontology. One can not create a new individual using rules of this form.

What is a Different Individuals Atom?

A different individuals atom consists of the differentFrom symbol and two arguments representing OWL individuals. Examples include:

    differentFrom(?x, ?y)
    differentFrom(Fred, Joe)

Here, ?x and ?y are variables representing OWL individuals, and Fred and Joe are the names of OWL individuals.

See below for an explanation of how this atom can be used in rules.

What is a Same Individual Atom?

A same individual atom consists of the sameAs symbol and two arguments representing OWL individuals. Examples include:

    sameAs(?x, ?y)
    sameAs(Fred, Freddy)

Here, ?x and ?y are variables representing OWL individuals, and Fred and Freddy are the names of OWL individuals.

See below for an explanation of how this atom can be used in rules.

What is a Data Range Atom?

A data range atom consists of a datatype name or a set of literals and a single argument representing a data value. Examples include:

    xsd:int(?x)
    [3, 4, 5](?x)

Here, ?x is a variable representing a data value.

What is a Built-In Atom?

One of the most powerful features of SWRL is its ability to support user-defined built-ins. A built-in is a predicate that takes one or more arguments and evaluates to true if the arguments satisfy the predicate. For example, an equal built-in can be defined to accept two arguments and return true if the arguments are the same. A number of core built-ins for common mathematical and string operations are contained in the SWRL Built-in Submission.

An example SWRL rule using a core SWRL built-in to indicate that a person with an age of greater than 17 is an adult is:

    Person(?p) ^ hasAge(?p, ?age) ^ swrlb:greaterThan(?age, 17) -> Adult(?p)

By convention, core SWRL built-ins are preceded by the namespace qualifier swrlb. When executed, this rule would classify individuals of class Person with an hasAge property value of greater than 17 as members of the class Adult.

A rule that uses a core SWRL string built-in to determine if a person's telephone number starts with the international access code "+" can be written as follows:

    Person(?p) ^ hasNumber(?p, ?number) ^ swrlb:startsWith(?number, "+") 
    -> hasInternationalNumber(?p, true)

Built-ins can take any number or combination of OWL datatype property values. Datatypes can be XML Schema Datatype or arbitrary user-defined types. They can not take object, class or property values. However, the SWRLAPI implementation of SWRL has custom extensions to allow arguments of these types.

The SWRL Submission does not provide a mechanism for specifying the number or types of built-in arguments - argument checking is the responsibility of the built-in implementor. The submission does specify that a built-in that is passed an incorrect number or arguments, or arguments of an incorrect type, should evaluate to false.

SWRL allows new libraries of built-ins to be defined and used in rules. Users can define built-in libraries to perform a wide range of tasks. Such tasks could, for example, include currency conversion, temporal manipulations, and taxonomy searches.

Can Built-Ins Bind their Arguments?

Yes - built-ins can also assign (or bind) values to arguments. For example, the SWRL atom swrlb:add(?x, 2, 3) uses the core SWRL built-in add method to add two integer literals. If x is unbound when this built-in is invoked, it will be assigned the the value 5 when the built-in returns. If x is already bound when the built-in is invoked, it will simply determine if its value is 5.

A built-in method that successfully assigns a value to an argument should return true. If more than one unbound argument is present, all arguments must be bound. If the built-in returns false no assignments are expected.

An example rule that uses built-ins with assignment to calculate the area of a rectangle can be be written as follows:

    Rectangle(?r) ^ hasWidthInMeters(?r, ?w) ^ hasHeightInMeters(?r, ?h) ^ 
    swrlb:multiply(?areaInSquareMeters, ?w, ?h) 
    -> hasAreaInSquareMeters(?r, ?areaInSquareMeters)

Since the areaInSquareMeters variable is unbound when the multiply built-in is called the built-in will assign a value so that the built-in predicate evaluates to true. If the variable is bound when the built-in is called its value will be used directly in predicate evaluation. The use of a variable in any non built-in atom automatically ensures it is bound (assuming the rule fires).

We can use a similar rule to classify a rectangle with an area of over 100 square meters as a BigRectangle:

    Rectangle(?r) ^ hasWidthInMetres(?r, ?w) ^ hasHeightInMetres(?r, ?h) ^ 
    swrlb:multiply(?areaInSquareMeters, ?w, ?h) ^ 
    swrlb:greaterThan(?100, ?areaInSquareMeters) 
    -> hasAreaInSquareMetres(?r, ?areaInSquareMeters) ^ BigRectangle(?r)

This rule illustrates the binding of a variable by one built-in and its subsequent use by another built-in in the same rule. The variable areaInSquareMeters is unbound when it is passed to the multiply built-in so a value is assigned to it; when the greater than built-in is called, it is passed this bound value.

Binding precedence is from left to right. As mentioned above, the use of a variable in a non built-in atom automatically binds it - these atoms take precedence over all built-in atoms.

Unbound variables may potentially occur in any argument position. For example, consider the following two rules, both of which convert a person's salary from pounds to dollars:

    Person(?p) ^ hasSalaryInPounds(?p, ?pounds) ^ swrlb:divide(?pounds, ?dollars, ?1.9) 
    -> hasSalaryInDollars(?p, ?dollars)
    Person(?p) ^ hasSalaryInPounds(?p, ?pounds) ^ swrlb:multiply(1.9, ?pounds, ?dollars) 
    -> hasSalaryInDollars(?p, ?dollars)

In these cases, the unbound dollars variable is in the second and third argument positions, respectively.

Unbound arguments may have more than one valid binding that satisfies the built-in. For example, the absolute value built-in invocation swrlb:abs(7, ?x) could be satisfied by both 7 and -7 as bindings for the variable x.

Of course, not all built-ins will perform argument binding. For example, supporting argument binding in the core SWRL greaterThan built-in would be counter intuitive. The designer of a built-in must decide which - if any - arguments are to be bound.

A discussion of the implementation issues of defining SWRL built-ins that bind arguments can be found here.

Can OWL Class Expressions be used in SWRL Rules?

Yes - SWRL also supports the use of OWL class expressions (also known as class descriptions) in rules. For example, a rule that classifies an individual as a parent if it is a member of a class with a hasChild property with a minimum cardinality of one can be written as follows:

    (hasChild >= 1)(?x) -> Parent(?x)

It is important to note that this rule does not state that all individuals with a child are parents. It says, instead, that all individuals that are members of an OWL class with the restriction that its hasChild property has a minimum cardinality of one. Individuals with no known children may be classified as parents with this rule.

Rules can also use class descriptions to assert conclusions about individuals:

    Parent(?x) -> (hasChild >= 1)(?x)

In this case, the rule is asserting that all individuals of class Parent have a hasChild property with a cardinality of one or greater. Similarly, we can use class descriptions to assert that if a publication has cardinality restriction of exactly one on its hasAuthor property we can conclude that it is a single author publication:

    Publication(?p) ^ (hasAuthor = 1)(?p) -> SingleAuthorPublication(?p) 

Of course, this type of conclusion can be stated in OWL alone and does not require SWRL.

All OWL class descriptions used in SWRL rules have identical semantics to OWL class descriptions used elsewhere in an OWL ontology. That is, they are logical statements. The rule:

    (hasChild >= 1)(?x) -> Parent(?x)

matches all individuals for which it can be proven (directly or indirectly) that they are members of a class that has the specified cardinality restriction on a hasChild property. It does not match all individuals in an OWL ontology that have one or more values for a hasChild property. Because of OWL's (and SWRL's) open world assumption, this rule may actually match individuals that have no values for the hasChild property in the current ontology but for which the existence of such values can be deduced from OWL axioms. It is not possible to express this type of match in SWRL.

Does SWRL adopt the Open World Assumption?

Yes. The most significant point to note about SWRL is that it shares OWL's open world assumption. For example, one might expect that a rule that infers that if two OWL individuals of type Author cooperate on the same publication that they are collaborators could be written as:

    Publication(?p) ^ hasAuthor(?p, ?y) ^ hasAuthor(?p, ?z) -> collaboratesWith(?y, ?z)

However, OWL's open world semantics do not allow one to assume that two individuals are automatically distinct if they have different names - that is, OWL does not have a unique name assumption. (Additionally, due to normal rule pattern matching, variables y and z can also match the same individual in this rule.)

As mentioned, SWRL supports sameAs and differentFrom atoms to determine if individuals refer to the same underlying individual or are distinct.

For example, a rule that indicates that individuals are cooperators if they are co-authors on a paper can use the differentFrom clause in association with an owl:allDifferents axiom declaration that states that all individuals of class Author are different from each other. It can be written as follows:

    Publication(?a) ^ hasAuthor(?x, ?y) ^ hasAuthor(?x, ?z) ^ differentFrom(?y, ?z) 
    -> cooperatedWith(?y, ?z)

Similarly, SWRL will only deduce that two individuals are the same as each other if there is an explicit owl:sameAs OWL axiom defined for the individuals in an ontology or if their sameness is entailed by other axioms in an ontology.

Because of the open world assumption, rules that attempt to enumerate individuals or properties in an ontology are not always possible. One can not write a rule that make an inference based on, say, the number of individuals or property values in an ontology unless OWL statements explicitly state those numbers. So, the following rule to deduce that a publication is a single author publication based on the number of its authors is not expressible in SWRL:

Publication(?p) ^ hasAuthor(?p,?a) ^ ''has exactly one hasAuthor value in current ontology'' -> SingleAuthorPublication(?p)

A publication may have only one known author but other authors may also exist - unless it has been explicitly stated using OWL axioms that they do not.

OWL's open world assumption assumption can also easily lead one to write rules that are less general than intended in some circumstances. Say, for example, we are asked to write a rule that defines an obsessed person as a person who owns a thing and is also obsessed by the thing. The most obvious formulation would be something like:

    Person(?x) ^ owns(?x, ?t) ^ isObsessedBy(?x, ?t) -> ObsessedPerson(?x)

However, this rule will miss equivalent individuals that represent the same thing owned by a person. A more general formulation would be:

    Person(?x) ^ owns(?x, ?t1) ^ isObsessedBy(?x, ?t2) ^ sameAs(?t1, ?t2) 
    -> ObsessedPerson(?x)

Does SWRL support Nonmonotonic Inference?

No. Like OWL, SWRL supports monotonic inference only. Hence, SWRL rules cannot be used to modify existing information in an ontology. If SWRL rules allowed such modifications nonmonotonicity would follow. For this reason, SWRL rules can not retract or remove information from an ontology.

For example, assume we have a rule that indicates that a driver older than 25 is insurable by assigning a boolean property to true:

    Driver(?d) ^ hasAge(?d, ?age) ^ swrlb:greaterThan(?age, 25) 
    -> isInsurable(?d, true)

This rule will add the value of true to the isInsurable property for all drivers that satisfy the antecedent. It does not change the existing value for that property. If, for example, a driver has a previous assignment of false for that property, a successful firing of this rule for that driver will result in the property having two values. If the isInsurable value if functional (which it most likely should be), an OWL reasoner will indicate an inconsistency when applied to the resulting ontology.

Similarly, one may be tempted to write the following rule to increment the age of a driver by one:

    Driver(?d) ^ hasAge(?d, ?age) ^ swrlb:add(?newage, ?age, 1) 
    -> hasAge(?d, ?newage)

As with the previous rule, a successful invocation of this rule will result in a driver having two values for their hasAge property, which is probably not the intention. Worse still, the rule will be invoked for each new value and continue to assign incremented age values indefinitely.

Does SWRL support Negation As Failure?

A further consequence of SWRL's monotonicity is that negation as failure is not supported. The following rule, for example, is not possible:

    Person(?p) ^ ¬ hasCar(?p, ?c) -> CarlessPerson(?p)

It is easy to see that the addition of a car to the ontology could invalidate this rule's conclusion. Only individuals with an explicit OWL axiom stating that they have no car can be safely be concluded to be without a car:

    Person(?p) ^ (hasCar = 0)(?p) -> CarlessPerson(?p)

Does SWRL support Classical Negation?

While SWRL does not support negated atoms or negation as failure, classical negation is possible in SWRL with the use of owl:complementOf class descriptions in rules. For example, we can write the following rule that asserts that of an individual is not a member of class Person then it should be classified as a member of the class NonHuman.

    (not Person)(?x) -> NonHuman(?x)

Of course, with OWL's (and SWRL's) open world assumption this conclusion can only be reached for individuals for which it can definitely be concluded that they can not be members of the of the class Person. For example, if an OWL axiom states that members of the classses Person and Dog are disjoint then this rule can safely conclude that all dogs are not humans.

Does SWRL support Disjunctions of Atoms?

No - only positive conjunctions of atoms are supported. So, for example, the following rule is not possible:

    A(?x) or B(?x) -> C(?x)

This restriction is easy to work around in most cases. In the case of this example, the following two rules will produce the intended effect:

    A(?x) -> C(?x)
    B(?x) -> C(?x) 

It is easy to see that the addition of disjunctions of atoms would complicate the language's semantics. Consider, for example, the rule:

    A(?x) or B(?y) -> C(?x)

It is unclear what action should be taken in the consequent of this rule if the antecedent matches an individual of type B but does not match any individuals of class A - the variable x would have no sensible binding.

A rule with disjunctions of atoms in its head could cause similar confusion. For example, if the rule

    C(?x) -> A(?x) or B(?x)

matches individuals of class C, should those individuals be classified as members of class A or B, or both?

However, a form of single rule logical disjunction is supported with the use of OWL class union descriptions in rules. The rule

    (A or B)(?x) -> C(?x)

will classify any individuals that are instances of classes A or B as instances of class C.

Does SWRL support OWL Full?

Not directly. SWRL's semantics are based on OWL DL so it SWRL does not support direct reasoning about classes or properties. OWL Full constructs, such as classes as property values, are not supported by the language. One cannot write a rule that, for example, deduced some new knowledge based on the fact that one class is a direct subclass of another. For the same reason, RDF or RDFS constructs, or OWL constructs such as owl:Class or owl:DatatypeProperty, can not be used in rules.

The SWRLAPI's implementation coupled with its support for user-defined built-ins allows some limited support for interacting with with OWL Full ontologies. The SWRLTab's built-in implementation supports the use OWL class names, property names, individual names, and XSD types as built-in arguments. With these extensions, built-ins can be defined that support OWL Full operations.

It should be noted that the formal guarantees provides by OWL and SWRL may be lost if these extensions are used to deduce new knowledge. Ideally, such built-ins should only be used for ontology querying. In the SWRLAPI, for example, these built-ins libraries were designed to be used with the SQWRL query language.

Does SWRL support RDF or RDFS?

No. SWRL is based is based on OWL DL and does not support RDF or RDFS. For example, RDFS class instances or RDF property relationships can not be reasoned with by SWRL rules. Also, RDF terms, such as rdfs:Class or rdf:type, can not be used.

Some RDF/RDFS ontologies can be converted to OWL. For example, standard RDFS constructs, such as rdfs:Class, rdfs:subClassOf and the like, can be mapped correctly to corresponding OWL constructs. SWRL rules could then be written using these OWL concepts.

Where are SWRL's Formal Semantics Defined?

SWRL's model-theoretic semantics are defined in the SWRL Submission. SWRL is built on OWL DL and provides more expressivity than OWL DL alone. However, it shares its formal semantics: conclusions reached by SWRL rules have the same formal guarantees as the conclusions reached using standard OWL constructs. SWRL's additional expressivity comes at the expense of ) decidability. That is, while OWL reasoners are guaranteed to terminate when classifying an OWL ontology, inference with SWRL rules is not.

When should I use SWRL?

As mentioned above, SWRL is built on OWL DL and shares its formal semantics. It is more expressive than OWL DL alone but this additional expressivity comes at the expense of decidability. However, depending on the underlying inference engine and the nature of a particular ontology and associated SWRL rules, the decidability caveat may have more theoretical than practical implications. As a general point, however, one should aim to stay within OWL if possible and only use SWRL when its additional expressive power is required.

What are DL-Safe SWRL Rules?

DL-Safe SWRL rules are a restricted subset of SWRL rules. These rules have the desirable property of decidability. Decidability is ensured by restricting rules to operate only on known individuals in an OWL ontology. More precisely, all variables in a DL-Safe SWRL rule bind only to known individuals in an ontology. For complex reasons (see here, for example), the ability to bind to individuals that are not known causes undecidability. Restricting rules to only bind known individuals has been proven to ensure decidability.

It may not be immediately obvious why variables in a SWRL rule would ever bind to anything other than known individuals. However, SWRL rules are not 'standalone' - they are a sort of OWL axiom and interact with other OWL axioms in an ontology.

Consider, for example, the following rule:

    Vehicle(?v) ^ Motor(?m) ^ hasMotor(?v, ?m) -> MotorizedVehicle(?v)

which classifies a vehicle as a motorized vehicle if it has a motor. Clearly, this rule will classify any individual of class Vehicle as a MotorizedVehicle if it has an associated hasMotor property with an individual of class Motor as a value.

Assume we now define a subclass of Vehicle called Car with the associated restriction (hasMotor some Motor) and define a single individual of this class in our ontology. Since we have stated that the car has a motor, we would expect that the car individual would be classified as a motorized vehicle. However, since there is no specific motor declared for the hasMotor property in the ontology (only the statement that it has some motor), a DL-safe implementation of a SWRL reasoner would not infer that the car is a MotorizedVehicle. Doing so would mean that the variable m in the rule be bound to an individual that is not explicitly known.

There are many other situations in which variables in SWRL rules could bind to individuals that are not known.

Clearly, DL-safety restricts the expressive power of SWRL somewhat. DL-Safe rules may produce incomplete inferences - that is, they may not generate all the deduction that are entailed by a particular ontology. However, any deductions that are reached are formally sound. It is important to note DL-safety is achieved by restricting the inferences reached by a SWRL reasoner, not by restricting the authoring of the rules themselves - DL-safe rules look exactly like normal SWRL rules.

Current OWL reasoners that support SWRL, such as, for example, Pellet, and KAON2, implement DL-Safe SWRL rules only. The SWRLAPI's OWL 2 RL-based implementation of SWRL is also DL-Safe.

However, if built-ins are used that bind their arguments then rules may become undecidable. Consider, for example, the following rule:

    Driver(?d) ^ hasAge(?d, ?age) ^ swrlb:add(?newage, ?age, 1) 
    -> hasAge(?d, ?newage)

At first sight, this rule appears to increment a driver's age by one. However, as discussed above, SWRL's inference is monotonic so instead than modifying a driver's age this rule generates an infinite number of ages for a driver, each age one greater than the previous age. Inference with this rule will never terminate.

Does SWRL support the use of annotation values to refer to OWL entities?

By default, named OWL entities (i.e., classes, properties, and individuals) are referred to directly in rules using their underlying OWL name (as stored in the rdf:ID or rdf:About attributes in OWL's RDF serialization, for example). In many OWL ontologies, however, this name is not meaningful and instead the values of annotation properties (e.g., rdfs:label) contain a user-friendly name. These annotation values can be used in rules by enclosing them in single quotes.

Assume, for example, the the class Driver has a selected annotation property value of 'a Driver'. The previous rule could then be written:

    'a Driver'(?d) ^ hasAge(?d, ?age) ...

The approach is the same when referring to both properties and individuals using annotation values.

One caveat is that, unlikely OWL entity names, annotation values are not necessarily unique. Annotation values that refer to more than one OWL entity can thus not be used in rules. Either the values should be made unique (which they probably should be in any case) or the underlying entity name should be used.

The appropriate user-visible annotation value is typically specified per entity at the tool level and the tool's SWRL editor component will be responsible for supporting the display and editing of the selected annotation. If the selected annotation for an entity is later changed to an alternate one (or if the annotation is unselected and the entity name reverts to the default underlying name) the editor should present the new value. The underlying representation remains the same irrespective of what annotation is used. A description of how the SWRLTab's implementation of SWRL deals with annotation values can be found here.

How do I debug SWRL Rules?

SWRL rule bases can be difficult to debug because exploring the potentially complex dependencies between rules can be cumbersome.

In the SWRLAPI, SQWRL can be used to facilitate this type of debugging.

Because SQWRL is based on SWRL and effectively uses a SWRL rule antecedent as a retrieval specification for a query, it can be used to examine the values of variables used in a rule.

For example, the rule:

   Person(?p) ^ hasAge(?p, ?age) ^ swrlb:greaterThan(?age, 17) -> Adult(?p)

can be easily turned in to a SQWRL query by replacing its consequent:

    Person(?p) ^ hasAge(?p, ?age) ^ swrlb:greaterThan(?age, 17) -> sqwrl:select(?p, ?age)

These queries can then be executed in the SQWRLQueryTab.