Example 20: Reasoning — AllegroGraph Python client 105.1.0 documentation

# Example 20: Reasoning

AllegroGraph supports the following RDFS and OWL predicates:

- `rdf:type`;

- `rdfs:domain`;

- `rdfs:range`;

- `rdfs:subClassOf`;

- `rdfs:subPropertyOf`;

- `owl:inverseOf`;

- `owl:sameAs`;

- `owl:SymmetricProperty`;

- `owl:TransitiveProperty`.

A more detailed description of reasoning support can be found in the Reasoner Tutorial chapter of AllegroGraph LISP documentation and is not repeated here for brevity. This tutorial only contains Python setup and querying examples.

## Setup

In order to enable reasoning, a connection to the server must be constructed by passing repository spec to a `reason()` function and creating a session from the resulting spec:

    conn = server.openSession(reason(repo))

This connection must be used instead of a regular connection as an entry-point to execute queries on inferred statements. Here is a complete example of a setup that enables RDFS++ reasoning over a regular repository `repo`:

    from franz.openrdf.sail.allegrographserver import AllegroGraphServer
    from franz.openrdf.sail.spec import reason

    server = AllegroGraphServer(host='localhost', port=10035, user='test', password='xyzzy')

    # Create repository 'repo' in the root catalog.
    server.openCatalog().createRepository('repo')

    # Open session with reasoning enabled on repository 'repo'.
    conn = server.openSession(reason('<repo>'))

## Reasoner examples

The examples below assume that you already have an RDFS++ repository created as described in the Setup section. Each example removes all of the triples in the store, adds some new triples, and makes some queries to illustrate the different sorts of reasoning that AllegroGraph supports.

In order to demonstrate the results, we will use the following function to print triples matching a simple pattern:

    def ptl(conn, s, p, o):
        """
        Get statements matching subject, predicate and object,
        which can be either entities represented by strings
        of the form '<prefix>:<name>' or wildcard None values.
        """
        namespaces = {
            'rdf': conn.namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#'),
            'ex': conn.namespace('ex://')
        }

        def part_to_uri(part):
            # Split part string on ':' and get a full URI from a corresponding
            # namespace object:
            if part:
                prefix, name = part.split(':', 2)
                return getattr(namespaces[prefix], name)
            else:
                return None

        us, up, uo = (part_to_uri(part) for part in (s, p, o))
        for rs, rp, ro, _ in conn.getStatements(us, up, uo):
            print("{} {} {}.".format(rs, rp, ro))

It is also possible to ask for inferred statements without creating a reasoning session by setting the value of the `includeInferred` argument to `getStatements()` to `True` as in the following example:

    conn.getStatements(s, p, o, includeInferred=True)

### `inverseOf`

    >>> conn.addData("""
    ...   @prefix owl: <http://www.w3.org/2002/07/owl#>.
    ...   @prefix ex: <ex://>.
    ...
    ...   ex:Jans    ex:owns       ex:Birra.
    ...   ex:ownedBy owl:inverseOf ex:owns.
    ...   ex:has     owl:inverseOf ex:ownedBy.
    ... """)

    >>> ptl(conn, "ex:Birra", "ex:ownedBy", None)
    <ex://Birra> <ex://ownedBy> <ex://Jans>.

    >>> ptl(conn, None, "ex:ownedBy", None)
    <ex://Birra> <ex://ownedBy> <ex://Jans>.

    >>> ptl(conn, None, "ex:ownedBy", "ex:Jans")
    <ex://Birra> <ex://ownedBy> <ex://Jans>.

    >>> ptl(conn, "ex:Jans", "ex:has", None)
    <ex://Jans> <ex://has> <ex://Birra>.

    >>> ptl(conn, None, "ex:has", None)
    <ex://Jans> <ex://has> <ex://Birra>.

    >>> ptl(conn, None, "ex:has", "ex:Birra")
    <ex://Jans> <ex://has> <ex://Birra>.

### `subPropertyOf`

    >>> conn.addData("""
    ...   @prefix owl: <http://www.w3.org/2002/07/owl#>.
    ...   @prefix ex: <ex://>.
    ...   @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
    ...
    ...   ex:Jans   ex:hasPet          ex:Birra.
    ...   ex:Birra  ex:friendOf        ex:Samira.
    ...   ex:hasPet rdfs:subPropertyOf ex:owns.
    ... """)

    >>> ptl(conn, "ex:Jans", "ex:owns", "ex:Birra")
    <ex://Jans> <ex://owns> <ex://Birra>.

    >>> ptl(conn, "ex:Jans", "ex:owns", None)
    <ex://Jans> <ex://owns> <ex://Birra>.

    >>> ptl(conn, None, "ex:owns", "ex:Birra")
    <ex://Jans> <ex://owns> <ex://Birra>.

    >>> ptl(conn, "ex:Jans", "ex:hasPet", "ex:Birra")
    <ex://Jans> <ex://hasPet> <ex://Birra>.

    >>> ptl(conn, "ex:Jans", "ex:hasPet", None)
    <ex://Jans> <ex://hasPet> <ex://Birra>.

    >>> ptl(conn, None, "ex:hasPet", "ex:Birra")
    <ex://Jans> <ex://hasPet> <ex://Birra>.

### `inverseOf` with `subPropertyOf`

    >>> conn.addData("""
    ...   @prefix owl: <http://www.w3.org/2002/07/owl#>.
    ...   @prefix ex: <ex://>.
    ...   @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
    ...
    ...   ex:Jans    ex:hasPet          ex:Birra.
    ...   ex:ownedBy owl:inverseOf      ex:owns.
    ...   ex:has     owl:inverseOf      ex:ownedBy.
    ...   ex:hasPet  rdfs:subPropertyOf ex:owns.
    ...   ex:petOf   owl:inverseOf      ex:hasPet.
    ... """)

    # direct triples
    >>> ptl(conn, "ex:Jans", "ex:hasPet", "ex:Birra")
    <ex://Jans> <ex://hasPet> <ex://Birra>.

    >>> ptl(conn, None, "ex:hasPet", "ex:Birra")
    <ex://Jans> <ex://hasPet> <ex://Birra>.

    >>> ptl(conn, "ex:Jans", "ex:hasPet", None)
    <ex://Jans> <ex://hasPet> <ex://Birra>.

    # inverse of ex:hasPet
    >>> ptl(conn, "ex:Birra", "ex:petOf", "ex:Jans")
    <ex://Birra> <ex://petOf> <ex://Jans>.

    >>> ptl(conn, None, "ex:petOf", "ex:Jans")
    <ex://Birra> <ex://petOf> <ex://Jans>.

    >>> ptl(conn, "ex:Birra", "ex:petOf", None)
    <ex://Birra> <ex://petOf> <ex://Jans>.

    # subproperty
    >>> ptl(conn, "ex:Jans", "ex:owns", "ex:Birra")
    <ex://Jans> <ex://owns> <ex://Birra>.

    >>> ptl(conn, "ex:Jans", "ex:owns", None)
    <ex://Jans> <ex://owns> <ex://Birra>.

    >>> ptl(conn, None, "ex:owns", "ex:Birra")
    <ex://Jans> <ex://owns> <ex://Birra>.

    # inverse of subproperty
    >>> ptl(conn, "ex:Birra", "ex:ownedBy", "ex:Jans")
    <ex://Birra> <ex://ownedBy> <ex://Jans>.

    >>> ptl(conn, None, "ex:ownedBy", "ex:Jans")
    <ex://Birra> <ex://ownedBy> <ex://Jans>.

    >>> ptl(conn, "ex:Birra", "ex:ownedBy", None)
    <ex://Birra> <ex://ownedBy> <ex://Jans>.

    # inverse of inverse
    >>> ptl(conn, "ex:Jans", "ex:has", "ex:Birra")
    <ex://Jans> <ex://has> <ex://Birra>.

    >>> ptl(conn, None, "ex:has", "ex:Birra")
    <ex://Jans> <ex://has> <ex://Birra>.

    >>> ptl(conn, "ex:Jans", "ex:has", None)
    <ex://Jans> <ex://has> <ex://Birra>.

### `sameAs`

    >>> conn.addData("""
      @prefix owl: <http://www.w3.org/2002/07/owl#>.
      @prefix ex: <ex://>.
      @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.

      ex:Jans   ex:owns    ex:Birra.
      ex:Jans   owl:sameAs ex:Jannes.
      ex:Aasman owl:sameAs ex:Jannes.
      ex:Birra  owl:sameAs ex:SonOfSamira.
    """)

    >>> ptl(conn, "ex:Aasman", "ex:owns", "ex:SonOfSamira")
    <ex://Aasman> <ex://owns> <ex://SonOfSamira>.

    >>> ptl(conn, "ex:Aasman", "ex:owns", None)
    <ex://Aasman> <ex://owns> <ex://Birra>.
    <ex://Aasman> <ex://owns> <ex://SonOfSamira>.

    >>> ptl(conn, None, "ex:owns", "ex:SonOfSamira")
    <ex://Jans> <ex://owns> <ex://SonOfSamira>.
    <ex://Jannes> <ex://owns> <ex://SonOfSamira>.
    <ex://Aasman> <ex://owns> <ex://SonOfSamira>.

    >>> ptl(conn, None, "ex:owns", None)
    <ex://Jans> <ex://owns> <ex://Birra>.
    <ex://Aasman> <ex://owns> <ex://Birra>.
    <ex://Aasman> <ex://owns> <ex://SonOfSamira>.
    <ex://Jannes> <ex://owns> <ex://SonOfSamira>.
    <ex://Jannes> <ex://owns> <ex://Birra>.
    <ex://Jans> <ex://owns> <ex://SonOfSamira>.

### `sameAs` with `inverseOf` and `subPropertyOf`

    conn.addData("""
      @prefix owl: <http://www.w3.org/2002/07/owl#>.
      @prefix ex: <ex://>.
      @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.

      ex:Jans    ex:hasPet ex:Birra.
      ex:ownedBy owl:inverseOf ex:owns.
      ex:has     owl:inverseOf ex:ownedBy.
      ex:hasPet  rdfs:subPropertyOf ex:owns.
      ex:petOf   owl:inverseOf ex:hasPet.
      ex:Birra   ex:age ex:twelve.

      ex:Jans   owl:sameAs ex:Jannes.
      ex:Aasman owl:sameAs ex:Jannes.
      ex:Birra  owl:sameAs ex:SonOfSamira.
    """)

    # direct triples
    >>> ptl(conn, "ex:Aasman", "ex:hasPet", "ex:SonOfSamira")
    <ex://Aasman> <ex://hasPet> <ex://SonOfSamira>.

    >>> ptl(conn, None, "ex:hasPet", "ex:SonOfSamira")
    <ex://Aasman> <ex://hasPet> <ex://SonOfSamira>.
    <ex://Jannes> <ex://hasPet> <ex://SonOfSamira>.
    <ex://Jans> <ex://hasPet> <ex://SonOfSamira>.

    >>> ptl(conn, "ex:Aasman", "ex:hasPet", None)
    <ex://Aasman> <ex://hasPet> <ex://Birra>.
    <ex://Aasman> <ex://hasPet> <ex://SonOfSamira>.

    # inverse of 'owns'
    >>> ptl(conn, "ex:SonOfSamira", "ex:petOf", "ex:Aasman")
    <ex://SonOfSamira> <ex://petOf> <ex://Aasman>.

    >>> ptl(conn, None, "ex:petOf", "ex:Aasman")
    <ex://SonOfSamira> <ex://petOf> <ex://Aasman>.
    <ex://Birra> <ex://petOf> <ex://Aasman>.

    >>> ptl(conn, "ex:SonOfSamira", "ex:petOf", None)
    <ex://SonOfSamira> <ex://petOf> <ex://Jannes>.
    <ex://SonOfSamira> <ex://petOf> <ex://Aasman>.
    <ex://SonOfSamira> <ex://petOf> <ex://Jans>.

    # inverse of inverse
    >>> ptl(conn, "ex:Aasman", "ex:has", "ex:SonOfSamira")
    <ex://Aasman> <ex://has> <ex://SonOfSamira>.

    >>> ptl(conn, None, "ex:has", "ex:SonOfSamira")
    <ex://Jannes> <ex://has> <ex://SonOfSamira>.
    <ex://Aasman> <ex://has> <ex://SonOfSamira>.
    <ex://Jans> <ex://has> <ex://SonOfSamira>.

    >>> ptl(conn, "ex:Aasman", "ex:has", None)
    <ex://Aasman> <ex://has> <ex://Birra>.
    <ex://Aasman> <ex://has> <ex://SonOfSamira>.

    # subproperty
    >>> ptl(conn, "ex:Aasman", "ex:owns", "ex:SonOfSamira")
    <ex://Aasman> <ex://owns> <ex://SonOfSamira>.

    >>> ptl(conn, "ex:Aasman", "ex:owns", None)
    <ex://Aasman> <ex://owns> <ex://SonOfSamira>.
    <ex://Aasman> <ex://owns> <ex://Birra>.

    >>> ptl(conn, None, "ex:owns", "ex:SonOfSamira")
    <ex://Aasman> <ex://owns> <ex://SonOfSamira>.
    <ex://Jans> <ex://owns> <ex://SonOfSamira>.
    <ex://Jannes> <ex://owns> <ex://SonOfSamira>.

    # inverse of subproperty
    >>> ptl(conn, "ex:SonOfSamira", "ex:ownedBy", "ex:Aasman")
    <ex://SonOfSamira> <ex://ownedBy> <ex://Aasman>.

    >>> ptl(conn, None, "ex:ownedBy", "ex:Aasman")
    <ex://SonOfSamira> <ex://ownedBy> <ex://Aasman>.
    <ex://Birra> <ex://ownedBy> <ex://Aasman>.

    >>> ptl(conn, "ex:SonOfSamira", "ex:ownedBy", None)
    <ex://SonOfSamira> <ex://ownedBy> <ex://Aasman>.
    <ex://SonOfSamira> <ex://ownedBy> <ex://Jans>.
    <ex://SonOfSamira> <ex://ownedBy> <ex://Jannes>.

### `type` with `subClassOf`

    >>> conn.addData("""
      @prefix owl: <http://www.w3.org/2002/07/owl#>.
      @prefix ex: <ex://>.
      @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
      @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.

      ex:Mammal rdfs:subClassOf ex:Animal.
      ex:Human  rdfs:subClassOf ex:Mammal.
      ex:Man    rdfs:subClassOf ex:Human.
      ex:Jans   rdf:type        ex:Man.
      ex:Jans   owl:sameAs      ex:Jannes.
      ex:Aasman owl:sameAs      ex:Jannes.
    """)

    >>> ptl(conn, "ex:Jans", "rdf:type", "ex:Man")
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Man>.

    >>> ptl(conn, "ex:Jans", "rdf:type", "ex:Human")
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.

    >>> ptl(conn, "ex:Jans", "rdf:type", None)
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Man>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Animal>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.

    >>> ptl(conn, "ex:Aasman", "rdf:type", "ex:Man")
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Man>.

    >>> ptl(conn, "ex:Aasman", "rdf:type", "ex:Human")
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.

    >>> ptl(conn, "ex:Aasman", "rdf:type", None)
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Animal>.
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Man>.

    >>> ptl(conn, None, "rdf:type", "ex:Man")
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Man>.

    >>> ptl(conn, None, "rdf:type", "ex:Human")
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.
    <ex://Jannes> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.

    >>> ptl(conn, None, "rdf:type", None)
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Man>.
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.
    <ex://Jannes> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.
    <ex://Jannes> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Animal>.
    <ex://Jannes> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Animal>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Animal>.

### `type` with `range`

    >>> conn.addData("""
      @prefix owl: <http://www.w3.org/2002/07/owl#>.
      @prefix ex: <ex://>.
      @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.

      ex:Jans   ex:hasPet      ex:Birra.
      ex:hasPet rdfs:range      ex:Pet.
      ex:Pet    rdfs:subClassOf ex:Mammal.
      ex:Fatcat owl:sameAs      ex:Birra.
    """)

    >>> ptl(conn, "ex:Birra", "rdf:type", "ex:Pet")
    <ex://Birra> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Pet>.

    >>> ptl(conn, "ex:Birra", "rdf:type", None)
    <ex://Birra> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Pet>.
    <ex://Birra> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.

    >>> ptl(conn, None, "rdf:type", "ex:Pet")
    <ex://Fatcat> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Pet>.
    <ex://Birra> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Pet>.

    >>> ptl(conn, "ex:Birra", "rdf:type", "ex:Mammal")
    <ex://Birra> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.

    >>> ptl(conn, "ex:Fatcat", "rdf:type", "ex:Mammal")
    <ex://Fatcat> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.

### `type` with `domain`

    >>> conn.addData("""
      @prefix owl: <http://www.w3.org/2002/07/owl#>.
      @prefix ex: <ex://>.
      @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.

      ex:Jans   ex:hasPet      ex:Birra.
      ex:hasPet rdfs:domain     ex:Human.
      ex:Human  rdfs:subClassOf ex:Mammal.
      ex:Jans   owl:sameAs      ex:Aasman.
    """)

    >>> ptl(conn, "ex:Jans", "rdf:type", "ex:Human")
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.

    >>> ptl(conn, "ex:Jans", "rdf:type", None)
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.

    >>> ptl(conn, None, "rdf:type", "ex:Human")
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.

    >>> ptl(conn, None, "rdf:type", None)
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Mammal>.
    <ex://Aasman> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.
    <ex://Jans> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex://Human>.

### Transitivity with `sameAs`

    >>> conn.addData("""
      @prefix owl: <http://www.w3.org/2002/07/owl#>.
      @prefix ex: <ex://>.
      @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.

      ex:contains    rdf:type    owl:TransitiveProperty.
      ex:USA         ex:contains ex:California.
      ex:GoldenState ex:contains ex:ContraCosta.
      ex:ContraCosta ex:contains ex:Moraga.

      ex:USA        owl:sameAs ex:UncleSam.
      ex:Moraga     owl:sameAs ex:MyTown.
      ex:California owl:sameAs ex:GoldenState.
    """)

    >>> ptl(conn, "ex:USA", "ex:contains", "ex:Moraga")
    <ex://USA> <ex://contains> <ex://Moraga>.

    >>> ptl(conn, "ex:UncleSam", "ex:contains", "ex:MyTown")
    <ex://UncleSam> <ex://contains> <ex://MyTown>.

    >>> ptl(conn, "ex:GoldenState", "ex:contains", "ex:Moraga")
    <ex://GoldenState> <ex://contains> <ex://Moraga>.

    >>> ptl(conn, "ex:California", "ex:contains", "ex:Moraga")
    <ex://California> <ex://contains> <ex://Moraga>.

    >>> ptl(conn, "ex:California", "ex:contains", "ex:MyTown")
    <ex://California> <ex://contains> <ex://MyTown>.

    >>> ptl(conn, "ex:USA", "ex:contains", None)
    <ex://USA> <ex://contains> <ex://California>.
    <ex://USA> <ex://contains> <ex://MyTown>.
    <ex://USA> <ex://contains> <ex://GoldenState>.
    <ex://USA> <ex://contains> <ex://ContraCosta>.
    <ex://USA> <ex://contains> <ex://Moraga>.

    >>> ptl(conn, "ex:UncleSam", "ex:contains", None)
    <ex://UncleSam> <ex://contains> <ex://GoldenState>.
    <ex://UncleSam> <ex://contains> <ex://California>.
    <ex://UncleSam> <ex://contains> <ex://ContraCosta>.
    <ex://UncleSam> <ex://contains> <ex://MyTown>.
    <ex://UncleSam> <ex://contains> <ex://Moraga>.

    >>> ptl(conn, None, "ex:contains", "ex:Moraga")
    <ex://ContraCosta> <ex://contains> <ex://Moraga>.
    <ex://California> <ex://contains> <ex://Moraga>.
    <ex://UncleSam> <ex://contains> <ex://Moraga>.
    <ex://GoldenState> <ex://contains> <ex://Moraga>.
    <ex://USA> <ex://contains> <ex://Moraga>.

    >>> ptl(conn, None, "ex:contains", "ex:MyTown")
    <ex://GoldenState> <ex://contains> <ex://MyTown>.
    <ex://USA> <ex://contains> <ex://MyTown>.
    <ex://ContraCosta> <ex://contains> <ex://MyTown>.
    <ex://UncleSam> <ex://contains> <ex://MyTown>.
    <ex://California> <ex://contains> <ex://MyTown>.