Skip to content

factppgraph

ontopy.factpluspluswrapper.factppgraph

FaCTPPGraph

Class for running the FaCT++ reasoner (using OwlApiInterface) and postprocessing the resulting inferred ontology.

Parameters

owlapi.Graph instance

The graph to be inferred.

Source code in ontopy/factpluspluswrapper/factppgraph.py
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
class FaCTPPGraph:
    """Class for running the FaCT++ reasoner (using OwlApiInterface) and
    postprocessing the resulting inferred ontology.

    Parameters
    ----------
    graph : owlapi.Graph instance
        The graph to be inferred.
    """

    def __init__(self, graph):
        self.graph = graph
        self._inferred = None
        self._namespaces = None
        self._base_iri = None

    @property
    def inferred(self):
        """The current inferred graph."""
        if self._inferred is None:
            self._inferred = self.raw_inferred_graph()
        return self._inferred

    @property
    def base_iri(self):
        """Base iri of inferred ontology."""
        if self._base_iri is None:
            self._base_iri = URIRef(self.asserted_base_iri() + "-inferred")
        return self._base_iri

    @base_iri.setter
    def base_iri(self, value):
        """Assign inferred base iri."""
        self._base_iri = URIRef(value)

    @property
    def namespaces(self):
        """Namespaces defined in the original graph."""
        if self._namespaces is None:
            self._namespaces = dict(self.graph.namespaces()).copy()
            self._namespaces[""] = self.base_iri
        return self._namespaces

    def asserted_base_iri(self):
        """Returns the base iri or the original graph."""
        return URIRef(dict(self.graph.namespaces()).get("", "").rstrip("#/"))

    def raw_inferred_graph(self):
        """Returns the raw non-postprocessed inferred ontology as a rdflib
        graph."""
        return OwlApiInterface().reason(self.graph)

    def inferred_graph(self):
        """Returns the postprocessed inferred graph."""
        self.add_base_annotations()
        self.set_namespace()
        self.clean_base()
        self.remove_nothing_is_nothing()
        self.clean_ancestors()
        return self.inferred

    def add_base_annotations(self):
        """Copy base annotations from original graph to the inferred graph."""
        base = self.base_iri
        inferred = self.inferred
        for _, predicate, obj in self.graph.triples(
            (self.asserted_base_iri(), None, None)
        ):
            if predicate == OWL.versionIRI:
                version = obj.rsplit("/", 1)[-1]
                obj = URIRef(f"{base}/{version}")
            inferred.add((base, predicate, obj))

    def set_namespace(self):
        """Override namespace of inferred graph with the namespace of the
        original graph.
        """
        inferred = self.inferred
        for key, value in self.namespaces.items():
            inferred.namespace_manager.bind(
                key, value, override=True, replace=True
            )

    def clean_base(self):
        """Remove all relations `s? a owl:Ontology` where `s?` is not
        `base_iri`.
        """
        inferred = self.inferred
        for (
            subject,
            predicate,
            obj,
        ) in inferred.triples(  # pylint: disable=not-an-iterable
            (None, RDF.type, OWL.Ontology)
        ):
            inferred.remove((subject, predicate, obj))
        inferred.add((self.base_iri, RDF.type, OWL.Ontology))

    def remove_nothing_is_nothing(self):
        """Remove superfluid relation in inferred graph:

        owl:Nothing rdfs:subClassOf owl:Nothing
        """
        triple = OWL.Nothing, RDFS.subClassOf, OWL.Nothing
        inferred = self.inferred
        if triple in inferred:
            inferred.remove(triple)

    def clean_ancestors(self):
        """Remove redundant rdfs:subClassOf relations in inferred graph."""
        inferred = self.inferred
        for (  # pylint: disable=too-many-nested-blocks
            subject
        ) in inferred.subjects(RDF.type, OWL.Class):
            if isinstance(subject, URIRef):
                parents = set(
                    parent
                    for parent in inferred.objects(subject, RDFS.subClassOf)
                    if isinstance(parent, URIRef)
                )
                if len(parents) > 1:
                    for parent in parents:
                        ancestors = set(
                            inferred.transitive_objects(parent, RDFS.subClassOf)
                        )
                        for entity in parents:
                            if entity != parent and entity in ancestors:
                                triple = subject, RDFS.subClassOf, entity
                                if triple in inferred:
                                    inferred.remove(triple)

add_base_annotations()

Copy base annotations from original graph to the inferred graph.

Source code in ontopy/factpluspluswrapper/factppgraph.py
73
74
75
76
77
78
79
80
81
82
83
def add_base_annotations(self):
    """Copy base annotations from original graph to the inferred graph."""
    base = self.base_iri
    inferred = self.inferred
    for _, predicate, obj in self.graph.triples(
        (self.asserted_base_iri(), None, None)
    ):
        if predicate == OWL.versionIRI:
            version = obj.rsplit("/", 1)[-1]
            obj = URIRef(f"{base}/{version}")
        inferred.add((base, predicate, obj))

asserted_base_iri()

Returns the base iri or the original graph.

Source code in ontopy/factpluspluswrapper/factppgraph.py
55
56
57
def asserted_base_iri(self):
    """Returns the base iri or the original graph."""
    return URIRef(dict(self.graph.namespaces()).get("", "").rstrip("#/"))

base_iri() property writable

Base iri of inferred ontology.

Source code in ontopy/factpluspluswrapper/factppgraph.py
35
36
37
38
39
40
@property
def base_iri(self):
    """Base iri of inferred ontology."""
    if self._base_iri is None:
        self._base_iri = URIRef(self.asserted_base_iri() + "-inferred")
    return self._base_iri

clean_ancestors()

Remove redundant rdfs:subClassOf relations in inferred graph.

Source code in ontopy/factpluspluswrapper/factppgraph.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
def clean_ancestors(self):
    """Remove redundant rdfs:subClassOf relations in inferred graph."""
    inferred = self.inferred
    for (  # pylint: disable=too-many-nested-blocks
        subject
    ) in inferred.subjects(RDF.type, OWL.Class):
        if isinstance(subject, URIRef):
            parents = set(
                parent
                for parent in inferred.objects(subject, RDFS.subClassOf)
                if isinstance(parent, URIRef)
            )
            if len(parents) > 1:
                for parent in parents:
                    ancestors = set(
                        inferred.transitive_objects(parent, RDFS.subClassOf)
                    )
                    for entity in parents:
                        if entity != parent and entity in ancestors:
                            triple = subject, RDFS.subClassOf, entity
                            if triple in inferred:
                                inferred.remove(triple)

clean_base()

Remove all relations s? a owl:Ontology where s? is not base_iri.

Source code in ontopy/factpluspluswrapper/factppgraph.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def clean_base(self):
    """Remove all relations `s? a owl:Ontology` where `s?` is not
    `base_iri`.
    """
    inferred = self.inferred
    for (
        subject,
        predicate,
        obj,
    ) in inferred.triples(  # pylint: disable=not-an-iterable
        (None, RDF.type, OWL.Ontology)
    ):
        inferred.remove((subject, predicate, obj))
    inferred.add((self.base_iri, RDF.type, OWL.Ontology))

inferred() property

The current inferred graph.

Source code in ontopy/factpluspluswrapper/factppgraph.py
28
29
30
31
32
33
@property
def inferred(self):
    """The current inferred graph."""
    if self._inferred is None:
        self._inferred = self.raw_inferred_graph()
    return self._inferred

inferred_graph()

Returns the postprocessed inferred graph.

Source code in ontopy/factpluspluswrapper/factppgraph.py
64
65
66
67
68
69
70
71
def inferred_graph(self):
    """Returns the postprocessed inferred graph."""
    self.add_base_annotations()
    self.set_namespace()
    self.clean_base()
    self.remove_nothing_is_nothing()
    self.clean_ancestors()
    return self.inferred

namespaces() property

Namespaces defined in the original graph.

Source code in ontopy/factpluspluswrapper/factppgraph.py
47
48
49
50
51
52
53
@property
def namespaces(self):
    """Namespaces defined in the original graph."""
    if self._namespaces is None:
        self._namespaces = dict(self.graph.namespaces()).copy()
        self._namespaces[""] = self.base_iri
    return self._namespaces

raw_inferred_graph()

Returns the raw non-postprocessed inferred ontology as a rdflib graph.

Source code in ontopy/factpluspluswrapper/factppgraph.py
59
60
61
62
def raw_inferred_graph(self):
    """Returns the raw non-postprocessed inferred ontology as a rdflib
    graph."""
    return OwlApiInterface().reason(self.graph)

remove_nothing_is_nothing()

Remove superfluid relation in inferred graph:

owl:Nothing rdfs:subClassOf owl:Nothing

Source code in ontopy/factpluspluswrapper/factppgraph.py
110
111
112
113
114
115
116
117
118
def remove_nothing_is_nothing(self):
    """Remove superfluid relation in inferred graph:

    owl:Nothing rdfs:subClassOf owl:Nothing
    """
    triple = OWL.Nothing, RDFS.subClassOf, OWL.Nothing
    inferred = self.inferred
    if triple in inferred:
        inferred.remove(triple)

set_namespace()

Override namespace of inferred graph with the namespace of the original graph.

Source code in ontopy/factpluspluswrapper/factppgraph.py
85
86
87
88
89
90
91
92
93
def set_namespace(self):
    """Override namespace of inferred graph with the namespace of the
    original graph.
    """
    inferred = self.inferred
    for key, value in self.namespaces.items():
        inferred.namespace_manager.bind(
            key, value, override=True, replace=True
        )

FactPPError

Postprocessing error after reasoning with FaCT++.

Source code in ontopy/factpluspluswrapper/factppgraph.py
8
9
class FactPPError:
    """Postprocessing error after reasoning with FaCT++."""