hasValue reasoning Introduction and Tutorial | AllegroGraph 9.0.1
Author: Franz Incorporated

Copyright (c) 2005 - 2026 Franz, Incorporated
Last updated 27 May 2026 at 10:34

# hasValue reasoning in AllegroGraph 9.0.1

- Documentation Index
  - Release Notes
  - Quick Start
  - SSL/TLS Quick Start
  - Introduction
  - Setup and Configuration
    - Download
    - Server Installation
    - Server Configuration and Control
    - WebView
    - Database Upgrading
    - Managing Users
  - Server Management
    - Performance Tuning
    - Deleting Duplicate Triples
    - Purging Deleted Triples
    - Auditing
    - Managing Users
    - Replication
    - Point-in-Time Recovery
    - Transaction Log Archiving
    - Security Overview
    - Security Implementation
  - Tools
    - agtool
    - Data Loading
    - Data Export
    - Backup and Restore
    - Querying
    - RDFS++
    - Materializer
    - Event Scheduler
    - SHACL
  - Details
    - Triple Indices
    - Freetext Indices
    - Encoded IDs
    - Connection Pooling
    - N-dimensional Geospatial Overview
    - 2-D Geospatial
    - Temporal
    - Social Network
    - JavaScript
    - Datatypes
    - Data Conversion (Rapper)
    - Stored Procedures
    - Triple Attributes
    - Lineparse Format
  - Querying
    - SPARQL documentation summary
    - SPARQL Reference
    - SPIN
    - SPARQL Magic Properties
    - Prolog
  - 3rd-party tools
    - Solr text Indices
    - MongoDB integration
    - TopBraid Composer Plugin
    - Cloudera
  - Client APIs
    - Gruff
    - GraphTalker
    - REST/HTTP interface
    - HTTP reference
    - Javadocs (Sesame and Jena)
    - Python API
    - Lisp Reference
    - JavaScript
  - Tutorials
    - N-dimensional Geospatial
    - SPARQL Tutorial
    - Java Sesame
    - Java Jena
    - Python Sesame
    - Lisp
    - Prolog
    - More...
  - Other
    - Conferences and Seminars
    - Source Code on Github
    - Amazon EC2
    - Copyrights
  - Franz, Inc.

- Introduction
- How to use hasValue reasoning
- How to use it from Lisp: a tutorial
  - Deriving default values from type information
  - Deriving types from value information

Documentation Index

## Introduction

In addition to RDFS++ reasoning, AllegroGraph also supports reasoning over hasValue restrictions in equivalent classes or subclasses.

For example, here is an owl class definition for AtlantisMission, defined as a SpaceMission where the `shuttleUsed` property has the value `Atlantis`.

    <owl:Class rdf:ID="AtlantisMission">
        <rdfs:subClassOf
            rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
        <rdfs:label
            rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
            Atlantis mission
        </rdfs:label>
        <owl:equivalentClass>
            <owl:Class>
                <owl:intersectionOf rdf:parseType="Collection">
                <rdf:Description rdf:ID="SpaceMission"/>
                <owl:Restriction>
                    <owl:onProperty rdf:resource="#shuttleUsed"/>
                    <owl:hasValue rdf:resource="#Atlantis"/>
                </owl:Restriction>
                </owl:intersectionOf>
            </owl:Class>
        </owl:equivalentClass>
    </owl:Class>

We can make two types of inferences from this definition.

1. We can derive the default value for `shuttleUsed` when we have an Instance of an AtlantisMission. For example, if a triple-store contains the the ontology definition above and we add the following triple:

       (add-triple
        !m:Mission4 !rdf:type !m:AtlantisMission)

then we can derive that the `shuttleUsed` property must be `Atlantis` with the following query.

    (select (?val)
      (q !m:Mission3 !m:shuttleUsed ?val))

2. The reasoning also works in reverse: we can derive the type of an instance to be an `AtlantisMission` if it has the right properties. If we added the following instance properties to a triple-store

       (add-triple
         !m:Mission5 !m:shuttleUsed !m:Atlantis)
       (add-triple
         !m:Mission5 !rdf:type !m:SpaceMission)

then the following query would derive that `?x` is an `AtlantisMission`.

    (select (?x)
      (q !m:Mission5 !rdf:type ?x))

hasValue reasoning is not enabled by default. The tutorial below will show how to turn this on.

## How to use hasValue reasoning

From Java
  See the description of setEntailmentRegime.
From Python
  On any Python API where `infer` or `includeInferred` is an argument, the values can be the boolean False (which means no reasoning), True, which is the same as "rdfs++", or the strings "rdfs++" (rdf++ reasoning but not hasValue reasoning) or "restriction" ("restriction" turns on hasValue reasoning as well as rdf++ reasoning).
From HTTP
  Set the `infer` parameter to `restriction` when using the repository interface of the HTTP protocol.

## How to use it from Lisp: a tutorial

In principle the following code will all run. Just evaluate every expression from top to bottom and you will see the results.

    ; load agraph into lisp
    (require :agraph)

    ; go into the triple-store-user package
    (in-package :triple-store-user)

    ;; make it easier to type URIs
    (enable-!-reader)

The following will define the function to load the files `SpaceMissions2.ntriples` into the triple-store. This file is included in the distribution. It will help you understanding of the contents of this file to inspect it in TopBraid Composer.

    (defun read-sm ()
      (create-triple-store  "test11")
      (load-ntriples "sys:agraph;tutorial-files;SpaceMissions2.ntriples"))

    (time (read-sm))                  ; do the actual read

We are lazy and don't want to type long namespaces:

    (register-namespace
      "m" "http://www.topbraid.org/spacemissions.owl#")

    ;; lets look at the triples..
    (print-triples *db* :limit nil :format :terse)

To use restriction reasoning, we must either apply-rdfs++-reasoner and then use restriction-reasoning-enabled-p or use the `initarg`.

    (apply-rdfs++-reasoner)
    (setf (restriction-reasoning-enabled-p *db*) t)

or

    (apply-rdfs++-reasoner :restriction-reasoning-enabled t)

### Deriving default values from type information

1. First we demonstrate how we to derive default values from type information

       (add-triple
         !m:Mission1 !rdf:type !m:SpaceMissionIn2000)
       (add-triple
         !m:Mission1 !m:added-by !m:Jans)

       (select (?x ?y)
         (q !m:Mission1 !m:startYear ?x)
         (q- !m:Mission1 !m:added-by ?y))

and some more examples:

    (add-triple
       !m:Mission3 !rdf:type !m:DiscoveryMission)
    (add-triple
       !m:Mission4 !rdf:type !m:AtlantisMission)

    (select (?val)
      (q !m:Mission3 !m:shuttleUsed ?val))

    (select (?val)
      (q !m:Mission4 !m:shuttleUsed ?val))

    (select ()
      (q !m:Mission4 !m:shuttleUsed !m:Atlantis)
      (write 'SUCCESS))

### Deriving types from value information

1. Second, we demo how we can derive types from values. We add the `shuttleUsed` property to `Mission5` and then we can automatically derive that `Mission5` is an `AtlantisMission`.

       (add-triple
         !m:Mission5 !m:shuttleUsed !m:Atlantis)

Now this `select` query returns two results:

    (select (?x)
      (q !m:Mission5 !rdf:type ?x))

    (("http://www.topbraid.org/spacemissions.owl#SpaceMission")
     ("http://www.topbraid.org/spacemissions.owl#AtlantisMission"))

The first result is due to the fact that the `rdfs:range` of the property `shuttleUsed` is 'SpaceMission'. So by adding the fact `shuttleUsed` to `Mission5` the RDFS++ range reasoning will derive that `Mission5` is a `SpaceMission`.

Then the `restriction` reasoning module uses the fact that `Misison5` is a `SpaceMission` and the `shuttleUsed` is `Atlantis` to derive that `Mission5` is an `AtlantisMission`.

The following queries are also interesting. The first select will only return `Mission4` because we use `q-` and `q-` looks only at the ground triples. It returns `Mission4` because we added that triple above:

    (select (?x)
      (q- ?x !rdf:type !m:AtlantisMission))
    -> (("http://www.topbraid.org/spacemissions.owl#Mission4"))

The following query returns `Mission4` and also `Mission5` because of `hasValue` reasoning. (Note how we use `q` here to use the reasoner)

    (select (?x)
      (q ?x !rdf:type !m:AtlantisMission))
    ->
    (("http://www.topbraid.org/spacemissions.owl#Mission4")
     ("http://www.topbraid.org/spacemissions.owl#Mission5"))

Now we can add some more triples:

    (add-triple !m:Mission6 !m:shuttleUsed !m:Columbia)
    (add-triple !m:Mission6 !rdf:type !m:SpaceMission)

    (select (?x)
      (q !m:Mission6 !rdf:type ?x))

    (select (?x)
      (q ?x !rdf:type !m:DiscoveryMission))

    (select ()
      (q !m:Mission6 !rdf:type !m:DiscoveryMission)
      (lisp (print 'SUCCESS)))

And finally we show that we can do quite complex `hasValue` restrictions. Please look in TopBraidComposer or any other ontology browser how a `MilitarySpaceMission` is defined by multiple `hasValue` restrictions.

We add some values and everything should work.

    (add-triple !m:Mission7 !rdf:type !m:SpaceMission)
    (add-triple !m:Mission7 !m:hasMissionType !m:SpecialMissionType)
    (add-triple !m:Mission7 !m:hasMissionType !m:MilitaryMissionType)

    (select (?x ?y)
      (q !m:Mission7 ?x ?y))

    (select (?type)
      (q !m:Mission7 !rdf:type ?type))

    (select (?x)
      (q ?x !rdf:type !m:MilitarySpaceMission))