ISWC 2026 Demo Submission Examples

Below are code cells corresponding to the figures of the ISWC 2026 short paper submission, plus additional details.

Figure 1

Parsing a sort subsumption + similarity

from fosf.parsers import parse_taxonomy
sim_tax_str = """
# Subsumption declarations
institution, person < top .
research_center < institution .
university < research_center .
researcher, lecturer, teacher < person .
professor < researcher, lecturer .
# Similarity declarations
teacher ~ lecturer = 0.5 ."""
sim_tax = parse_taxonomy(sim_tax_str)

Drawing the fuzzy taxonomy

from fosf.utils.draw import notebook_display as display
display(sim_tax, drop="bot", similarity=sim_tax._similarity)
../_images/76eee84be82555f0727855b7ea7f00f51e35427528fcb32002b4c4b472377ce5.png

Computing GLBs

from fosf.syntax import Sort
researcher, teacher = Sort("researcher"), Sort("teacher")
sim_tax.glb(researcher, teacher)
Sort('professor')

Checking sort subsumption

professor = Sort("professor")
sim_tax.is_subsort(professor, teacher)
True

Computing subsumption degrees

sim_tax.degree(professor, teacher)
np.float64(0.5)
person = Sort("person")
sim_tax.degree(professor, person)
1.0

Figure 2

Parsing an OSF term and normalizing it according to the sort subsumption + similarity.

from fosf.parsers import parse_term
from fosf.reasoning import normalize_term
# Normalizing an OSF term according to subsumption + similarity only
t_str = "X0:person(teach_at -> X1:institution, research_at -> X1:research_center)"
t = parse_term(t_str)
print(normalize_term(t, sim_tax))
# Output: X0 : person(teach_at -> X1 : research_center, research_at -> X1)
X0 : person(teach_at -> X1 : research_center, research_at -> X1)
display(normalize_term(t, sim_tax))
../_images/2a7b5853807ed57c0ff3bbf9c5f95d0dbef2a500bd71de8e3e8ae3826b7f96bc.png

Figure 3

from fosf.parsers import parse_theory
theory_str = sim_tax_str + """
professor           := Yp:professor(research_at -> Y1:university) .
domain(teach_at)    := teacher .
domain(research_at) := researcher ."""
theory = parse_theory(theory_str, ensure_closed=True)
# Normalizing an OSF term also according to the theory
nt, degree = normalize_term(t, sim_tax, theory, return_degree=True)
print(degree, nt)
# Output: 0.5 X0 : professor(teach_at -> X1 : university, research_at -> X1)
0.5 X0 : professor(teach_at -> X1 : university, research_at -> X1)
display(nt)
../_images/8f507eac0de703ba8cc42ce78cb3c485df9cac592131aafcfdd21de81936935f.png

The satisfaction degree of nt with respect to the OSF theory:

print(degree)
0.5

Figure 4

The initial term $t$:

t.pretty_print()
X0 : person(
    teach_at -> X1 : institution
    research_at -> X1 : research_center
)

Its SPARQL translation of Figure 4(a):

print(t.to_sparql())
prefix : <http://example.org/>
SELECT DISTINCT ?X0 WHERE {
  ?X0 rdf:type :person .
  ?X0 :teach_at ?X1 .
  ?X1 rdf:type :institution .
  ?X0 :research_at ?X1 .
  ?X1 rdf:type :research_center .
}

The term $t$ after normalization according to the OSF theory:

nt.pretty_print()
X0 : professor(
    teach_at -> X1 : university
    research_at -> X1
)

Its SPARQL translation of Figure 4(b):

nt_sparql = nt.to_sparql()
print(nt_sparql)
prefix : <http://example.org/>
SELECT DISTINCT ?X0 WHERE {
  ?X0 rdf:type :professor .
  ?X0 :teach_at ?X1 .
  ?X1 rdf:type :university .
  ?X0 :research_at ?X1 .
}

Extra: normalization and translation without the similarity relation

# Same theory minus the similarity teacher ~ lecturer
no_sim_theory_str = """
institution, person < top .
research_center < institution .
university < research_center .
researcher, lecturer, teacher < person .
professor < researcher, lecturer .

professor           := Yp:professor(research_at -> Y1:university).
domain(teach_at)    := teacher . domain(research_at) := researcher .
"""
no_sim_theory = parse_theory(no_sim_theory_str)

Normalizing $t$ according to this theory:

no_sim_nt = normalize_term(t, no_sim_theory.taxonomy, no_sim_theory)
no_sim_nt.pretty_print()
_FAIL : bot

:bot is the bottom sort, corresponding to the empty set.

The SPARQL translation:

print(no_sim_nt.to_sparql())
prefix : <http://example.org/>
SELECT DISTINCT ?_FAIL WHERE {
  ?_FAIL rdf:type :bot .
}

Query answering

The generated SPARQL queries can be run on in-memory RDF graphs (via rdflib) or remote SPARQL endpoints (via SPARQLWrapper).

from rdflib import Graph
turtle = """@prefix : <http://example.org/> .
:alice a :professor ; :teach_at :unimib ; :research_at :unimib .
:unimib a :university . """
g = Graph().parse(data=turtle)
print(g.query(nt.to_sparql()).serialize(format='csv').decode())
X0
http://example.org/alice

The cell below demonstrates how to send the compiled SPARQL query to a remote endpoint using SPARQLWrapper. If you do not have a SPARQL server running locally at http://localhost:8890/sparql, the cell will catch the connection error.

from urllib.error import URLError
from SPARQLWrapper import SPARQLWrapper

endpoint_url = "http://localhost:8890/sparql"
try:
    endpoint = SPARQLWrapper(endpoint_url)
    endpoint.setQuery(nt.to_sparql())
    endpoint.setReturnFormat('csv')
    print(endpoint.query().convert().decode())
except (ConnectionRefusedError, URLError):
    print(f"Note: local SPARQL endpoint not running at {endpoint_url}.")
    print("To execute this query, start a local triple store or point SPARQLWrapper to a public endpoint.")
"X0"
"http://example.org/alice"