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}