N3 rule examples

© Jean-Marc Vanel - $Date: 2012-09-30$ - under Creative Commons License

The rule examples are classified by domain. For a comprehensive presentation by design patterns, see companion document "N3 rules: good practices, design patterns, refactoring".

Some of the examples are "a priori" N3 rules, some were obtained from Attempto Controlled English (ACE, see in EulerGUI Manual Working with controlled (formal) english through Ace View ). In the latter case the ACE text is in italics. We leave as an exercise to the reader how to write an ACE sentence that will match the a priori N3 rules.

Thanks to: Kaarel Kaljurand, Norbert E. Fuchs, Jos de Roo, Olivier Rossel, Nassim Douali .

TOC

Business rules and other rules

Business rules are rules that are purely logical and manipulate only domain (business) concepts, as the examples in this documentation.

The "applicative" rules express application requirements on the application itself: under what circumstances it will show something, or offer the user to update the data.

The "constructive"rules create information, such as the "friend suggestions" rule below.

Constraints are imposed by "integrity constraints" rules, which have false in the right hand side.

Forward chaining rule engine

Commerce

If there is an order there is a demand for payment associated:

{ ?O a Order } => { ?D a DemandForPayment . ?O hasPaymentRequest ?D. }.

ACE: If there is an order O then there is a demand-for-payment D, and D is associated-to O .

If the bearer has had an incident of payment, then the order is canceled:

{ ?C hasHolder ?H .?H hasPaymentIncident ?PI } =>{ ?C hasStatus cancelled }.

If one customer has Ordered items in same Domain but different Category than the last items, propose this different Category to customer:

{ ?CUSTOMER :hasOrderedItem ?ITEM .?ITEM :domain ?DOMAIN .
  ?ITEM :category ?CATEGORY .?ITEM2 :belongsTo :lastItems .
  ?ITEM2 :domain ?DOMAIN .?ITEM2 :category ?CATEGORY2 .
  ?CATEGORY2 log:notEqualTo ?CATEGORY .
} => {:proposal :category ?CATEGORY2 } .


This other example starts from an ACE sentence:

If a customer has an addrress

whose country is not France

then the customer is a foreign-customer .

Via ACE View it is translated this way in OWL :

customer and (have some 
(addrress and (country some 
(owl:Thing and (not ({France})))))) SubClassOf foreign-customer

Enterprise management

Transportation

If a busLine X1 has-as-departure a town X2,

and X1 has-as-arrival a town X4,

and the town X4 belongs-to a country X3,

and the town X2 belongs-to the country X3

then the busLine X1 is a nationalBusLine .

{?t0 a ns1:busLine. ?t3 a ns1:country. ?t2 a ns1:town. ?t1 a ns1:town.
 ?t2 ns1:belongs-to ?t3. ?t1 ns1:belongs-to ?t3.
 ?t0 ns1:has-as-arrival ?t1. ?t0 ns1:has_as_departure ?t2}
=> {?t0 a ns1:nationalBusLine}.

N3 data example:

Ind172872104613704311 has-as-departure Toulouse .

Ind172872104613704311 has-as-arrival Paris .

Paris belongs-to France .

Toulouse belongs-to France .

France is a country .

Every town belongs-to one country .

Physic modeling: algebraic expressions

There are currently problems with algebraic expressions in core ACE Prolog .

In some cases OWL Functional-Style Syntax works, but OWL-RDF does not.

Some problems have been corrected by Kaarel and EulerGUI team, but is not yet in the APE (ACE) distribution.

.

The ACE to OWL+SWRL translator used in ACE View has its own limitations, in addition to ACE (ATTEMPTO) limitations. So one must adapt the sentences to ACE View by transforming one intransitive verb into 2 transitive verbs ( e.g. travels ==> travels-during ) . This snippet works:

For each mobile M

for each n : acceleration G

for each n:elapsed-time T

there is a distance D

such that M v:travels-during the n:elapsed-time T ,

and M travels the distance D,

and D is ( 1 / 2 ) * G * T * T .

Same for the simpler sentence (variable D has been removed, but semantics is downgraded):

For each mobile M for each n : acceleration G for each n:elapsed-time T there is a distance D such that M v:travels-during the n:elapsed-time T , and M travels ( 1 / 2 ) * G * T * T .


Here is a simpler example with an algebraic formula :

If a n : rectangle R has a n : length L1 ,

and R has a n : length L2 ,

and S = ( L1 * L2 )

then R v : has-surface S .

The SWRL translation gives:

length(?x2) , length(?x4) , rectangle(?x1) , Thing(?x6) , have(?x1, ?x2) , have(?x1, ?x4) , multiply(?x6, ?x2, ?x4) -> has-surface(?x1, ?x6)

After translation to N3 this becomes:

{?t2 a ns1:length.
 ?t3 a ns1:length.
 ?t0 a ns1:rectangle.
 ?t0 ns1:have ?t2.
 ?t0 ns1:have ?t3.
 (ns1:x2 ns1:x4) math:product ?t1} => {?t0 ns1:has-surface ?t1}.

Note how nicely the semantics (not only the formula) has been preserved along the processing chain.

ACE example in materials science

% ape.exe -text 'Every n:concrete v:contains a n:cement and v:contains an n:aggregate.' -solo paraphrase 
Every n:concrete v:contains a n:cement and v:contains an aggregate.

% ape.exe -text 'Every n:concrete v:contains a n:cement and v:contains an n:aggregate.' -solo owlfsspp   
Prefix(:=<http://attempto.ifi.uzh.ch/ontologies/owlswrl/test#>)
Ontology(<http://attempto.ifi.uzh.ch/ontologies/owlswrl/test>
   SubClassOf(
      :concrete
      ObjectIntersectionOf(
         ObjectSomeValuesFrom(
            :contains
            :cement
         )
         ObjectSomeValuesFrom(
            :contains
            :aggregate
         )
      )
   )
)

In EulerGUI, this gives:

{ ?VAR a ns2:concrete
} => {
  ?t0 a ns2:aggregate. ?t1 a ns2:cement. ?VAR ns2:contains ?t0. ?VAR ns2:contains ?t1 }.

Social networks

Here is Facebook style rule :

If a user U has-as-friend a person X, and has-as-friend a person Y, and X is not Y,

and X has-as-friend Z, and Y has-as-friend Z, and Z is not U

then Z is-a-proposed-friend-for U.

Note the composite verbs that express a property assignment, typical of ACE View.

After translation to N3 (through SWRL) this becomes:

{?t0 a ns1:person.
 ?t1 a ns1:person.
 ?t2 a ns1:user.
 ?t2 ns1:has-as-friend ?t0.
 ?t2 ns1:has-as-friend ?t1.
 ?t0 ns1:has-as-friend ?t3.
 ?t1 ns1:has-as-friend ?t3.
 ?t0 owl:differentFrom ?t1.
 ?t3 owl:differentFrom ?t2} => {?t3 ns1:is-a-proposed-friend-for ?t2}.

Medicine

Adult Body Mass Index rule, created by Hans Cools:

{
  ?adult fos:complexity ?body.
  ?body a humanbody:Body; quex:hasPhysicalQuantity ?length, ?weight.
  ?length a humanbody:Length; quex:hasValue ?lengthValue; quex:hasUnit ?lengthUnit.
  ?weight a humanbody:Weight; quex:hasValue ?weightValue; quex:hasUnit ?weightUnit.
  (?lengthValue 2) math:exponentiation ?lengthValue2.
  (?weightValue ?lengthValue2) math:quotient ?X.
  (?X 10) math:product ?Y.
  ?Y math:rounded ?Z.
  (?Z 10) math:quotient ?BMI.
}
=> {?adult humanbody:hasBMI ?BMI.}.

Jos de Roo is developing a series of OWL ontologies and rules in N3, mostly related to medicine :

http://eulersharp.svn.sourceforge.net/viewvc/eulersharp/trunk/2003/03swap/?sortby=date#dirlist

There are rules for fuzzy logic.

Workplace and Human Resources

Everybody who lives-at a place that he/she works-at is a home-worker.

Alas currently ACE introduces an unnecessary extra variable in the SWRL translation:

      Consequent(
         description(
            Class(:home-worker)
            I-variable(5)
         )
         sameAs(
            I-variable(1)
            I-variable(5)
         )
      )

Queries on classes and properties

You can open in EulerGUI any ontolgy in RDFS, OWL/RDF, or OWL/XML, and apply rules in N3, such as :

Software infrastructure

Finite State Machine

Leveraging on the dynamic (stateful) capability of the Drools/N3 engine, it is possible to implement a Finite State Machine (FSM) in N3 in EulerGUI, and embed it in your application with the EulerGUI API.

The possible transitions (a.k.a. transition table) are determined by statements :possible_transition :s1 :s2 . Of course, these statements can be either facts, or infered by some rules.

The transition rule is triggered when :event :current :a_new_event is asserted :

{ :state :current ?S0. :event :current ?E. :possible_transition ?S0 ?S1.
} => {
  _:d kb:retract (:state :current ?S0).
  _:d kb:retract (:event :current ?E).
  :state :current ?S1.
}.

Other examples with dynamic behavior include :

examples/domotic.n3p : leverage on Drools' insertLogical()

test/builtins.n3p : usage of kb:retract

"make" utility

The make utility brings things up-to-date with their dependencies. This can be useful within a ruuning application as well, e.g for implementing caches, lazy evaluations, etc. A RETE (forward chaining) engine is well suited to implement that.

The generic rule for triggering a redo is:

{ ?TARGET :hasDependency ?DEP. ?TARGET :hasTimestamp ?TT. ?DEP :hasTimestamp ?TDEP.
  ?TT math:lessThan ?TDEP.
} => {
  ?TARGET :state :needsRedo.
}.

A user rule for redoing a target must include the update of the timestamp.

{
  ?TARGET :state :needsRedo.
} => {
  # target specific commands ...
  ?TARGET :update :timestamp.
}.

The generic rule for updating timestamp is:

{
  ?TARGET :update :timestamp.
} => {
  _:d kb:retract (?TARGET :hasTimestamp ?TT).
  ?NOW a java:java-util-Date.
  ?NOW java:time ?TNOW.
  ?TARGET :hasTimestamp ?TNOW.
}.

Family relationships

We sketch a rule base on kinship with:

For instance the rule for sibling is:

{ ?X hasParent ?P .
  ?Y hasParent ?P .
  ?X log:notEqualTo ?Y .
} => {
  ?X hasSibling ?Y }.

The rule for uncle is:

{ ?X hasParent ?P .
  ?P hasBrother ?B .
} => {
  ?X hasUncle ?B }.

The rest is left as exercise :) .

Rules matching rules

Here is an example of a rule about rules, see complete rule base in model-rules-coherence.n3 :

{
  ?A => ?C .
  ?A log:includes { ?S ?P ?O } .
  _:d e:findall ( () {?P a rdf:Property} () ).
} => {
  ?P :message ( "predicate not declared as Property "
        "; appears in antecedent of rule " { ?A => ?C } ).
} .

Rules creating rules

There are 2 rules bases that create N3 rules, one from SWRL rules, one from OWL axioms:

Both are activated within EulerGUI when an RDF or OWL URI is loaded .