001package org.dllearner.algorithms.schema;
002
003import org.apache.jena.rdf.model.Model;
004import org.aksw.jena_sparql_api.core.QueryExecutionFactory;
005import org.apache.log4j.ConsoleAppender;
006import org.apache.log4j.Level;
007import org.apache.log4j.LogManager;
008import org.apache.log4j.SimpleLayout;
009import org.dllearner.utilities.OwlApiJenaUtils;
010import org.dllearner.utilities.owl.DLSyntaxObjectRendererExt;
011import org.semanticweb.owlapi.apibinding.OWLManager;
012import org.semanticweb.owlapi.io.ToStringRenderer;
013import org.semanticweb.owlapi.model.*;
014import org.semanticweb.owlapi.util.DefaultPrefixManager;
015import org.slf4j.Logger;
016import org.slf4j.LoggerFactory;
017
018import java.util.Enumeration;
019import java.util.HashSet;
020import java.util.Set;
021import java.util.SortedSet;
022
023/**
024 * Generate a schema restricted to RDFS language features.
025 *
026 * The idea is to define an order when each axiom type has to be investigated. For RDFS this is given by the analysis
027 * of the RDFS reasoning rules, especially those that contain the corresponding predicates listed below.
028 *
029 * RDFS reasoning rule ordering:
030 *
031 * Transitive Rules(rdfs5, rdfs11)
032 * SubProperty Inheritance Rule(rdfs7)
033 * Domain/Range Rules(rdfs2, rdfs3)
034 * SubClass Inheritance Rules(rdfs9)
035 *
036 * Order of axiom types:
037 *
038 * 1. rdfs:subPropertyOf
039 * 2. rdfs:subClassOf
040 * 3. rdfs:domain
041 * 4. rdfs:range
042 *
043 *
044 * @author Lorenz Buehmann
045 */
046public class RDFSSchemaGenerator extends AbstractSchemaGenerator {
047
048        private static final Logger LOGGER = LoggerFactory.getLogger(RDFSSchemaGenerator.class);
049
050        private Set<OWLAxiom> learnedAxiomsTotal;
051
052        public RDFSSchemaGenerator(QueryExecutionFactory qef) {
053                super(qef);
054        }
055
056        public RDFSSchemaGenerator(OWLOntology ontology) {
057                super(OwlApiJenaUtils.getModel(ontology));
058        }
059
060        public RDFSSchemaGenerator(Model model) {
061                super(model);
062        }
063
064        @Override
065        public Set<OWLAxiom> generateSchema() {
066                LOGGER.info("generating RDFS schema...");
067                learnedAxiomsTotal = new HashSet<>();
068
069                // 1. learn property hierarchies
070                learnTransitiveClosure(AxiomType.SUB_DATA_PROPERTY, EntityType.DATA_PROPERTY);
071                learnTransitiveClosure(AxiomType.SUB_OBJECT_PROPERTY, EntityType.OBJECT_PROPERTY);
072
073                // 2. learn class hierarchy
074                learnTransitiveClosure(AxiomType.SUBCLASS_OF, EntityType.CLASS);
075
076                // 3. learn domain
077                learnIterative(AxiomType.DATA_PROPERTY_DOMAIN, EntityType.DATA_PROPERTY);
078                learnIterative(AxiomType.OBJECT_PROPERTY_DOMAIN, EntityType.OBJECT_PROPERTY);
079
080                // 3. learn range
081                learnIterative(AxiomType.DATA_PROPERTY_RANGE, EntityType.DATA_PROPERTY);
082                learnIterative(AxiomType.OBJECT_PROPERTY_RANGE, EntityType.OBJECT_PROPERTY);
083
084                return learnedAxiomsTotal;
085        }
086
087        private void learnIterative(AxiomType axiomType, EntityType entityType) {
088                LOGGER.debug("computing {} axioms ...", axiomType.getName());
089                SortedSet<OWLEntity> entities = getEntities(entityType);
090                for (OWLEntity entity : entities) {
091                        try {
092                                // apply learning algorithm
093                                Set<OWLAxiom> learnedAxioms = applyLearningAlgorithm(entity, axiomType);
094
095                                // add learned axioms to KB
096                                addToKnowledgebase(learnedAxioms);
097
098                                // keep track of all learned axioms
099                                learnedAxiomsTotal.addAll(learnedAxioms);
100                        } catch (Exception e) {
101                                LOGGER.error("Failed to learn " + axiomType.getName() + " axioms for entity " + entity, e);
102                        }
103                }
104        }
105
106        private void learnTransitiveClosure(AxiomType axiomType, EntityType entityType) {
107                LOGGER.debug("computing {} hierarchy ...", entityType.getPrintName().toLowerCase());
108                Set<OWLAxiom> learnedAxiomsTotal = new HashSet<>();
109
110                SortedSet<OWLEntity> entities = getEntities(entityType);
111
112                boolean newAxiomsLearned = !entities.isEmpty();
113
114                // fixpoint iteration
115                int i = 1;
116                while(newAxiomsLearned) {
117                        LOGGER.debug("iteration {}", i++);
118                        Set<OWLAxiom> learnedAxiomsInIteration = new HashSet<>();
119                        for (OWLEntity entity : entities) {
120                                System.out.println(entity);
121                                try {
122                                        // apply learning algorithm
123                                        Set<OWLAxiom> learnedAxioms = applyLearningAlgorithm(entity, axiomType);
124                                        LOGGER.debug("new axioms: " + learnedAxioms);
125
126                                        // add learned axioms to KB
127//                                      addToKnowledgebase(learnedAxioms);
128
129                                        learnedAxiomsInIteration.addAll(learnedAxioms);
130                                } catch (Exception e) {
131                                        LOGGER.error("Failed to learn " + axiomType.getName() + " axioms for entity " + entity, e);
132                                }
133                        }
134
135                        // stop if no new axioms learned
136                        if(!learnedAxiomsTotal.addAll(learnedAxiomsInIteration)) {
137                                newAxiomsLearned = false;
138                        }
139
140                        // add learned axioms to KB
141                        addToKnowledgebase(learnedAxiomsInIteration);
142
143                }
144
145                // keep track of all learned axioms
146                this.learnedAxiomsTotal.addAll(learnedAxiomsTotal);
147        }
148
149        public static void main(String[] args) throws Exception {
150                ToStringRenderer.getInstance().setRenderer(new DLSyntaxObjectRendererExt());
151
152                org.apache.log4j.Logger.getRootLogger().setLevel(Level.INFO);
153                org.apache.log4j.Logger.getRootLogger().removeAllAppenders();
154                org.apache.log4j.Logger.getRootLogger().addAppender(new ConsoleAppender(new SimpleLayout()));
155                org.apache.log4j.Logger.getLogger(RDFSSchemaGenerator.class).setLevel(Level.DEBUG);
156
157                Enumeration<org.apache.log4j.Logger> currentLoggers = LogManager.getCurrentLoggers();
158                while(currentLoggers.hasMoreElements()) {
159                        org.apache.log4j.Logger logger = currentLoggers.nextElement();
160                        System.out.println(logger.getName());
161                }
162
163                OWLOntologyManager man = OWLManager.createOWLOntologyManager();
164                OWLDataFactory df = man.getOWLDataFactory();
165                OWLOntology ont = man.createOntology(IRI.create("http://dllearner.org/test/"));
166
167                PrefixManager pm = new DefaultPrefixManager();
168                pm.setDefaultPrefix("http://dllearner.org/test/");
169
170                OWLClass clsA = df.getOWLClass("A", pm);
171                OWLClass clsB = df.getOWLClass("B", pm);
172                OWLClass clsC = df.getOWLClass("C", pm);
173
174                // A(a_i)
175                for (int i = 0; i < 10; i++) {
176                        man.addAxiom(ont, df.getOWLClassAssertionAxiom(clsA, df.getOWLNamedIndividual("a" + i, pm)));
177                }
178
179                // B(a_i)
180                for (int i = 0; i < 15; i++) {
181                        man.addAxiom(ont, df.getOWLClassAssertionAxiom(clsB, df.getOWLNamedIndividual("a" + i, pm)));
182                }
183
184                // C(a_i)
185                for (int i = 10; i < 15; i++) {
186                        man.addAxiom(ont, df.getOWLClassAssertionAxiom(clsC, df.getOWLNamedIndividual("a" + i, pm)));
187                }
188
189                RDFSSchemaGenerator gen = new RDFSSchemaGenerator(ont);
190                gen.setAccuracyThreshold(0.6);
191
192                Set<OWLAxiom> schema = gen.generateSchema();
193                schema.forEach(System.out::println);
194        }
195}