Axioms

Useful Rules, Axioms, and Mappings for GoodRelations

On this page, we are collecting optional rules and axioms and linksets for GoodRelations that are not part of the formal ontology specification but can be helpful in many cases.

They can be imported in your model when they don't hurt. Some have side-effects that are unwanted in some scenarios.

Such rules are not part of the core GoodRelations ontology for two reasons:

  • For semantic aligments with other vocabularies ("ontology mappings"), the problem is that the candidate vocabularies are often defined in different ontology languages or language fragments, e.g. RDF-S, OWL DL, and OWL Full. Including such alignments in GoodRelations directly will turn GoodRelations into OWL Full, which is something we want to avoid as much as we can. The reason is that there are applications for GoodRelations both
    *in the "open, wild Web", where OWL Full will anyway be the likely language fragment, and incomplete, lightweight reasoning be sufficient, and
    *in controlled, corporate settings, where staying within OWL DL is an important feature for consistent DL reasoning.
    Also, those alignments that are useful in practice are often broader than correct. While they are good in 90% of the cases, they will have unwanted side-effects in 10% of the cases. Thus, including them must be optional
  • For additional rules and axioms, the problem is that they raise the bar for computing the full entailment, which may slow down reasoner performance. Also, they are very promising topics for further research and fine-tuning, so the examples given in here will be initial sketches only. Practitioners will be able to improve them a lot in terms of computational efficiency and quality. If you are working on business applications that consume GoodRelations data, this is what you should dedicate resources to.

The following rules should be used by default for any GoodRelations data. They require just a simple rule reasoner.

Product Models

In GoodRelations, you can link a product or service (both gr:Individual (former gr:ActualProductOrServiceInstance) and gr:SomeItems (former gr:ProductOrServicesSomeInstancesPlaceholder)) to a make and model (gr:ProductOrServiceModel), i.e. the "datasheet" that specifies technical features for all those individual objects.

Now, our intuition tells us that an actual product inherits all technical features from its make and model, unless specified at for that particular individual specifically.

Example: If the Nikon camera model T80 has a weight of 400 g, then a camera instance of which is known that it is of this make and model can be inferred to weight 400 g, too.
SPARQL CONSTRUCT Rule:

# Products inherit all product features from their product models
# unless they are defined for the products individually

CONSTRUCT {?product ?property ?valueModel.}
WHERE
{
 {
   {?product a gr:Individual.}
   UNION
   {?product a gr:ActualProductOrServiceInstance.}
   UNION
   {?product a gr:SomeItems.}
   UNION
   {?product a gr:ProductOrServicesSomeInstancesPlaceholder.}
 }
   ?model a gr:ProductOrServiceModel.
   ?product gr:hasMakeAndModel ?model.
   ?model ?property ?valueModel.
 {
   {?property rdfs:subPropertyOf gr:qualitativeProductOrServiceProperty.}
   UNION
   {?property rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty.}
   UNION
   {?property rdfs:subPropertyOf gr:datatypeProductOrServiceProperty.}
 }
 OPTIONAL {?product ?property ?valueProduct.}
 FILTER (!bound(?valueProduct))
}

Possible extensions:Additional rules for gr:isConsumableFor, gr:isSimilarTo, and gr:isAccessoryOrSparePartFor.

(Previous page: Ruleset for Product Model Properties, now redirects to this section.)

Expand gr:includes

The gr:includes property is a shortcut for the many cases in which the product includes just one item. By that you spare the effort for an additional gr:TypeAndQuantityNode or even the gr: SomeItems node. However, when querying, you should search for the full pattern, or both. In order to expand all usages of gr:includes to the full pattern, activate the following TWO (!) SPARQL CONSTRUCT rules

Note: In the 2010-09-16 service update of GoodRelations, the usage of gr:includes is being expanded to links between gr:Offering and gr:ProductOrServiceModels, which can drastically reduce the markup effort.
SPARQL CONSTRUCT Rule #1:

# Expand gr:includes between gr:Offering and gr:SomeItems (older variant)

PREFIX gr: <http://purl.org/goodrelations/v1#>

CONSTRUCT {
  ?o gr:includesObject _:n .
  _:n rdf:type gr:TypeAndQuantityNode.
  _:n gr:amountOfThisGood "1.0"^^xsd:float.
  _:n gr:hasUnitOfMeasurement "C62"^^xsd:string.
  _:n gr:typeOfGood ?p.
}
WHERE {
  ?o rdf:type gr:Offering.
  {
    { ?p rdf:type gr:ProductOrServicesSomeInstancesPlaceholder. }
    UNION
    { ?p rdf:type gr:SomeItems. }
    UNION
    { ?p rdf:type gr:ActualProductOrServiceInstance . }
    UNION
    { ?p rdf:type gr:Individual. }
  }
  ?o gr:includes ?p.

  # Avoid duplicate expansion
  # (because that would multiply the amount of items included in the offer
  OPTIONAL {
    ?o gr:includesObject ?c.
    ?c gr:typeOfGood ?p.
  }
  FILTER (!bound(?c))
}

SPARQL CONSTRUCT Rule #2:

# Expand gr:includes between gr:Offering and gr:ProductOrServiceModel (newer variant)

PREFIX gr: <http://purl.org/goodrelations/v1#>

CONSTRUCT {
  # Type and Quantity Node
  ?o gr:includesObject _:tqn .
  _:tqn rdf:type gr:TypeAndQuantityNode.
  _:tqn gr:amountOfThisGood "1.0"^^xsd:float.
  _:tqn gr:hasUnitOfMeasurement "C62"^^xsd:string.
  # Product Placeholder
  _:tqn gr:typeOfGood _:p.
  _:p rdf:type gr:SomeItems.
  _:p gr:hasMakeAndModel ?m.
}
WHERE {
  ?o rdf:type gr:Offering.
  ?m rdf:type gr:ProductOrServiceModel.
  ?o gr:includes ?m.

  # Avoid duplicate expansion
  # (because that would multiply the amount of items included in the offer)
  OPTIONAL {
    ?o gr:includesObject ?tqn.
    ?tqn gr:typeOfGood ?ps.
    ?ps gr:hasMakeAndModel ?m.
  }
  FILTER (!bound(?tqn))
}

Product Variants

The gr:isVariantOf object property allows for modeling product model variants. This states that a particular ProductOrServiceModel instance is a variant of another ProductOrServiceModel. It is pretty safe to infer that the variant inherits all gr:quantitativeProductOrServiceProperties, gr:qualitativeProductOrServiceProperties, and gr:datatypeProductOrServiceProperties that are defined for the first gr:ProductOrServiceModel, except for those defined for the variant individually.

Exception:gr:hasEAN_UCC-13 and gr:hasStockKeepingUnit should not be inferred for the variant.
Example: foo:Red_Ford_T_Model gr:isVariantOf foo:Ford_T_Model

Note 1: gr:isVariantOf is NOT a transitive property in GoodRelations, because the semantics of defaults is a bit more complicated. In particular, the order of reasoning steps matters. If A is a variant of B and C a variant of B, then B should first inherit properties from A and C from B, before C would inherit properties from A. Otherwise, properties defined at the level of B could be overwritten by properties defined at the level of A. This problem is relevant only if model data overwrites product features at intermediate levels AND if there is more than one level of variantOf relationships. A pragmatic solution is to execute the construct rule a few times sequentially.

Note 2: There is a problem with quantitative values held in blank nodes in the current rule, because such may not be properly replicated. Avoid blank nodes for quantitative values, if possible.

SPARQL CONSTRUCT Rule:

# Rule for product variants
CONSTRUCT { ?model2 ?property ?valueModel1.}
WHERE {
  ?model1 a gr:ProductOrServiceModel.
  ?model2 a gr:ProductOrServiceModel.
  ?model2 gr:isVariantOf ?model1.
  ?model1 ?property ?valueModel1.
  {
    {?property rdfs:subPropertyOf gr:qualitativeProductOrServiceProperty.}
    UNION
    {?property rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty.}
    UNION
    {?property rdfs:subPropertyOf gr:datatypeProductOrServiceProperty.}
    FILTER (?property!=<http://purl.org/goodrelations/v1#hasEAN_UCC-13> &&
            ?property!=<http://purl.org/goodrelations/v1#hasStockKeepingUnit>)
  }
  OPTIONAL {?model2 ?property ?valueModel2.}
  FILTER (!bound(?valueModel2) && ?model1!=?model2)
}

Data Cleansing: Entity Consolidation Etc.

The distributed character of the Web makes it very likely that the exact same entity is being defined in multiple graphs. In particular, there will be significant redundancy in the definition of
- Business Entities and
- Product Models.

The main cause is that providers of data may define entities locally rather than searching for an authoritative URI on the Web. For example, someone exporting a catalog may want to refer to the manufacturer of a gr:ProductOrServiceModel or gr:SomeItems without searching for the authoritative URI of that manufacturer.  This is not a major technical problem, since providers of commerce dataspaces will very likely offer entity consolidation as one important feature.

For  your own projects, you can start with the following simple SPARQL CONSTRUCT rules to create owl:sameAs statements so that multiple definition of the very same entities will be treated as one.

# Add gr:hasMakeAndModel links between models and products
# on the basis of identical EAN_UCC codes
CONSTRUCT {?product gr:hasMakeAndModel ?model}
WHERE
{
  ?model a gr:ProductOrServiceModel.
  {
    {?product a gr:ProductOrServicesSomeInstancesPlaceholder.}
    UNION
    {?product a gr:SomeItems.}
    UNION
    {?product a gr:ActualProductOrServiceInstance.}
    UNION
    {?product a gr:Individual.}
  }
  ?model gr:hasEAN_UCC-13 ?ean.
  ?product gr:hasEAN_UCC-13 ?ean.
  OPTIONAL {?product gr:hasMakeAndModel ?model2}
  FILTER (?ean!="" && ?model != ?model2)
}

Consolidate Business Entities that have the exact same gr:legalName

CONSTRUCT {?u2 owl:sameAs ?u1.}
WHERE   {
  ?u1 a gr:BusinessEntity.
  ?u2 a gr:BusinessEntity.
  ?u1 gr:legalName ?name1.
  ?u2 gr:legalName ?name2.
  FILTER (?u1!=?u2 && ?name1=?name2)
}

Consolidate Product Models that have the exact same gr:hasEAN_UCC-13

CONSTRUCT {?u2 owl:sameAs ?u1.}
WHERE {
  ?u1 a gr:ProductOrServiceModel.
  ?u2 a gr:ProductOrServiceModel.
  ?u1 gr:hasEAN_UCC-13 ?ean1.
  ?u2 gr:hasEAN_UCC-13 ?ean2.
  FILTER (?u1!=?u2 && ?ean1=?ean2 && ?ean1!="")
}

On Openlink Virtuoso, you can use

! bif:isnull (?ean1)

instead of

?ean1 != ""

which will be faster.

Note that the current rules assume perfect equivalence of the legal names resp. the EAN/UPC code. You could use more sophisticated filters for expanding the scope of the consolidation, e.g. ignoring capitalization and special characters (e.g. "Miller Ltd." vs. "miller ltd").

Important:
1. Make sure you consolidate only nodes of the same type. For example, two gr:Offerings may have the same gr:hasEAN_UCC-13 property, but are of course not the same.
2. For local sets of such statements, you have any degree of freedom and I encourage you to experiment with different ones. Before publishing such sameAs statements, however, run thorough quality checks first. Reckless usage of sameAs can spam the Web of Linked Data, and dataspaces will consequently ignore all your graphs.

The following mapping rules are very much recommended and should practically have no unwanted side-effects, other than turning your data into OWL Full:

# GoodRelations Mappings
# Author: Martin Hepp, mheppATcomputerDOTorg

@prefix gr: <http://purl.org/goodrelations/v1#> .

# FOAF
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
gr:BusinessEntity rdfs:subClassOf foaf:Agent .
gr:legalName rdfs:subPropertyOf foaf:name .

# DBPedia
# This used to be gr:LocationOfSalesOrServiceProvisioning
gr:Location rdfs:subClassOf <http://dbpedia.org/ontology/Place> .

# DC
@prefix dcterms: <http://purl.org/dc/terms/> .
gr:name rdfs:subPropertyOf dcterms:title .
gr:description rdfs:subPropertyOf dcterms:description .

# RDFS
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
gr:name rdfs:subPropertyOf rdfs:label .
gr:description rdfs:subPropertyOf rdfs:comment .

# ECLASSOWL 5.1.4
@prefix eco: <http://www.ebusiness-unibw.org/ontologies/eclass/5.1.4/#> .
eco:P_BAA271001 rdfs:subPropertyOf gr:hasEAN_UCC-13 .
eco:P_BAA316001 rdfs:subPropertyOf gr:name . # Produkt-Name
eco:P_BAD847001 rdfs:subPropertyOf gr:hasMPN . # Hersteller-Artikelnummer
eco:P_BAJ011001 rdfs:subPropertyOf gr:hasStockKeepingUnit . # Lieferanten-Artikelnummer
eco:P_BAA059001 rdfs:subPropertyOf gr:hasStockKeepingUnit . # Artikelnummer
eco:P_BAA002001 rdfs:subPropertyOf gr:hasMPN . # Produkt-Typbezeichnung
eco:P_BAA001001 rdfs:subPropertyOf gr:name . # Hersteller-Name
eco:P_BAE344001 rdfs:subPropertyOf gr:hasMPN . # Hersteller-Model-Code
eco:P_BAA019001 rdfs:subPropertyOf gr:width . # Width
eco:P_BAB577001 rdfs:subPropertyOf gr:depth . # Depth
eco:P_BAA020001 rdfs:subPropertyOf gr:height . # Height

# CEO tbd
@prefix ceo: <http://www.ebusiness-unibw.org/ontologies/consumerelectronics/v1#> .

# Geo and Geonames tbd
@prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .

# Yahoo tbd
@prefix media: <http://search.yahoo.com/searchmonkey/media/> .
@prefix commerce: <http://search.yahoo.com/searchmonkey/commerce/> .

# Vehicle Sales Ontology tbd
@prefix vso: <http://purl.org/vso/ns#> .

# Dublin Core
@prefix dc: <http://purl.org/dc/elements/1.1/> .

# Vcard
@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .

# Schema.org
@prefix schema: <http://schema.org/> .
##  Alignment: Classes
schema:Person rdfs:subClassOf gr:BusinessEntity.
schema:Organization rdfs:subClassOf gr:BusinessEntity.
# The former is implied by the following, but few RDF environments
# can compute this inference
gr:BusinessEntity owl:equivalentClass  [
    a owl:Class;
    owl:unionOf (schema:Person schema:Organization) ].
schema:Product owl:equivalentClass gr:ProductOrService.

gr:Individual rdfs:subClassOf schema:Product.
# a bit too broad re services, but best pragmatic choice

gr:SomeItems rdfs:subClassOf schema:Product.
# a bit too broad re services, but best pragmatic choice

gr:ProductOrServiceModel rdfs:subClassOf schema:Product.
# a bit too broad re services, but best pragmatic choice

schema:Place owl:equivalentClass gr:Location.
schema:Offer rdfs:subClassOf gr:Offering.
# because gr:Offering may also represent demand

##  Alignment: Properties
schema:description owl:equivalentProperty gr:description.
# This may trigger slightly incorrect rdfs:domain inferences,
# but best pragmatic choice
schema:name owl:equivalentProperty gr:name.
# This may trigger slightly incorrect rdfs:domain inferences,
# but best pragmatic choice
schema:image owl:equivalentProperty foaf:depiction.

# the following can have the unintended side-effect that an identifier
# attached to a gr:Offering makes the entity also a schema:Product.
# but RDFS range reasoning is rarely important in real scenarios
gr:hasEAN_UCC-13 rdfs:subPropertyOf schema:productID.
gr:hasGTIN-14 rdfs:subPropertyOf schema:productID.
gr:hasGTIN-8 rdfs:subPropertyOf schema:productID.
gr:hasMPN rdfs:subPropertyOf schema:productID.
gr:hasStockKeepingUnit rdfs:subPropertyOf schema:productID.
schema:manufacturer owl:equivalentProperty gr:hasManufacturer.
# schema:offers is inverse of gr:includes, in a sense,
# but hard to formulate logically.

The following schema mappings are often useful in practice. While they are good in 90% of the cases, they will have unwanted side-effects in 10% of the cases. Thus, including them must be optional. In particular, they may turn your model into OWL Full.

Acknowledgements: A big thanks to Andreas Harth (ahaATaifb.uni-karlsruhe.de) for several suggestions!

@prefix ical: <http://www.w3.org/2002/12/cal/ical#>
gr:validFrom rdfs:subPropertyOf ical:DTSTART .
gr:validThrough rdfs:subPropertyOf ical:DTEND .


Candidates:

  • Locations: maybe foaf:based_near and geo:Point
  • Yahoo / foaf: Match foaf:depiction and media:image


Category:Added schema.org mapping Category:Developer