W3C | Semantic Web | Advanced Development | SWAP | Tutorial | Rules and Formulae

Rules and Formulae

We are going to learn how to express rules in N3, which will allow us to do all kinds of things. A simple rule might say something like (in some central heating vocabulary) "If the thermostat temperature is high, then the heating system power is zero", or

{ :thermostat :temp :high } log:implies { :heating :power "0" } .

The curly brackets here enclose a set of statements. Until this point, all statements in each file have been effectively in one bucket. They are all generated when the file is parsed, and stored in a store on an equal footing. In a rule, however, we need to talk about hypothetical statements: If this were the case then that would be the case. The statements within the brackets are not asserted like the other ones in the file. In the case above, the file does not say that the thermostat temperature is high. It just says that the left-hand formula implies the right-hand formula.

You see that, apart from the fact that the subject and object of the statement are formulae, the line above is just a single statement. log:implies is a special predicate which links formulae. The statement is a fact. Rules are in general facts, and on the semantic web they may or not be used by various programs at various times to figure things out.

The curly brackets are important. They do take us out of the things we can represent using the current RDF/XML OWL specifications. ((Formulae are (2003/2) a longer-term issue for the RDF Core group). Cwm will in most cases serialize formulae using an XML syntax which is not standard.

Variables

In fact, formulae in N3 are more than just sets of statements. They also allow declarations of variables. A variable is like just a symbol (such as :x or var:Y) except it is used to stand for other symbols. There are two types. A "forAll" or universal variable, declared like this,

@forAll :x.
{ :thermostat :temp :x } log:implies { :cooling :power :x } .

means that all this information is true even if the symbol ":x" is replaced consistently by something else. This is of course what you want for a rule which implies something generally about anything. The "this" indicates the scope of the variable - it in fact stands for the formula in which it is, in this case the outermost formula of the document. In most cases for simple rules, the variables are quantified in the scope of the document, but when things get nested, it is wise to think about what you mean. We don't deal with it in detail here. Mathematically, the formula above might be written

∀ x ( temp ( thermostat , x ) ⇒ power ( cooling , x ) )

A formula can also have "forSome", or existential, variables. They are declared as in

@forSome :a.
:Joe :home :a.
:a :phone "555-1212".

This means that there is something which is Joe's home and has the given phone number. We've been doing this all along, though, surely, with blank nodes. Indeed - most times that an existential variable is used it is actually implicit in the [bracket] syntax.

:Joe :home [ :phone "555-1212" ].

Each pair of square brackets actually stands for an unnamed existential variable. Cwm will generally use square brackets on output when it can - if there are loops then one has to use explicit variables.

@forSome :a.
:Joe :home :a.
:a :owner :Joe.
:a :phone "555-1212".

Variables with ? and _:

So far we have introduce variables for rules using @forAll. We have introduced existential variables (blank nodes) with @forSome. These are extensions to the RDF world to allow N3 to express rules. There are shortcuts under certain circumstances, which avoid you having to type them.

When a variable is universally quantified in not the formula itself but the surrounding formula, then you can just use ?x. This is in fact what you want for rules which don't have nested formulae inside the antecedent.

So instead of

@forAll :x, :y.
{ :x :parent :y } =>  { :y :child :x }.

you can write

{ ?x parent ?y } =>  { ?y :child ?x }.

which means just the same. We will use this all the time when writing simple rules. If you need the same variable to appear at several levels, then you can't use this form.

The other shortcut is that if you have existentially qualified variables in the scope of the whole document, then you can use _:a and so on. (This is the same as the ntriples notation)

So instead of writing

@forSome :a, :b.
:a :hates :b.   :b :loves :a.

you could just write

_:a :hates _:b.   _:b :loves _:a.

In practice this is very often used in ntriples but in N3, you can normally use the [] syntax to avoid using any variables at all.

Shorthand symbols for implies, etc.

When it is used as a predicate (verb) in N3, log:implies and => are the same; owl:equivalentTo and = are the same.

So, having gone into a few details of universal and existential identifiers, what we are left with is a pretty simple rule language, which is still a fairly straightforward extension of RDF.

{?x family:parent ?y. ?y family:brother ?z} => {?x family:uncle ?z}.

(Always remember the dot after the rule.)

Now let's learn how to process them.


References


Thanks to contributors including Joseph Reagle who added the uncle example to the original primer.
Tim BL, with his director hat off
$Id: Rules.html,v 1.13 2006/01/16 15:44:07 timbl Exp $