001/** 002 * Copyright (C) 2007 - 2016, Jens Lehmann 003 * 004 * This file is part of DL-Learner. 005 * 006 * DL-Learner is free software; you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation; either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * DL-Learner is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package org.dllearner.algorithms.properties; 020 021import org.dllearner.core.AbstractAxiomLearningAlgorithm; 022import org.dllearner.core.config.ConfigOption; 023import org.dllearner.learningproblems.AxiomScore; 024import org.dllearner.learningproblems.Heuristics; 025import org.semanticweb.owlapi.model.OWLLogicalAxiom; 026import org.semanticweb.owlapi.model.OWLObject; 027import org.semanticweb.owlapi.model.OWLProperty; 028 029import org.apache.jena.query.ParameterizedSparqlString; 030import org.apache.jena.query.ResultSet; 031import org.apache.jena.rdf.model.Model; 032 033/** 034 * A learning algorithm for property axioms. 035 * @author Lorenz Buehmann 036 * 037 */ 038public abstract class PropertyAxiomLearner<S extends OWLProperty, T extends OWLLogicalAxiom, V extends OWLObject> extends AbstractAxiomLearningAlgorithm<T, V, S>{ 039 040 protected static final ParameterizedSparqlString TRIPLES_COUNT_QUERY = new ParameterizedSparqlString( 041 "SELECT (COUNT(*) as ?cnt) WHERE {?s ?p ?o .}"); 042 043 protected static final ParameterizedSparqlString DISTINCT_SUBJECTS_COUNT_QUERY = new ParameterizedSparqlString( 044 "SELECT (COUNT(DISTINCT(?s)) as ?cnt) WHERE {?s ?p ?o .}"); 045 046 protected static final ParameterizedSparqlString DISTINCT_OBJECTS_COUNT_QUERY = new ParameterizedSparqlString( 047 "SELECT (COUNT(DISTINCT(?o)) as ?cnt) WHERE {?s ?p ?o .}"); 048 049 protected static final ParameterizedSparqlString GET_SAMPLE_QUERY = new ParameterizedSparqlString( 050 "CONSTRUCT {?s ?p ?o.} WHERE {?s ?p ?o}"); 051 052 protected ParameterizedSparqlString COUNT_QUERY = TRIPLES_COUNT_QUERY; 053 054 @ConfigOption(defaultValue = "true", description = "make SPARQL OWL queries a bit more strict (currently: also test " + 055 "if a class is an owl:Class in some cases)") 056 protected boolean strictOWLMode = true; 057 058 // a property domain axiom can formally be seen as a subclass axiom \exists r.\top \sqsubseteq \C 059 // so we have to focus more on accuracy, which we can regulate via the parameter beta 060 double beta = 3.0; 061 062 private boolean useSimpleScore = true; 063 064 065 /* (non-Javadoc) 066 * @see org.dllearner.core.AbstractAxiomLearningAlgorithm#setEntityToDescribe(org.semanticweb.owlapi.model.OWLEntity) 067 */ 068 @Override 069 public void setEntityToDescribe(S entityToDescribe) { 070 super.setEntityToDescribe(entityToDescribe); 071 072 posExamplesQueryTemplate.setIri("p", entityToDescribe.toStringID()); 073 negExamplesQueryTemplate.setIri("p", entityToDescribe.toStringID()); 074 075 COUNT_QUERY.setIri("p", entityToDescribe.toStringID()); 076 DISTINCT_SUBJECTS_COUNT_QUERY.setIri("p", entityToDescribe.toStringID()); 077 DISTINCT_OBJECTS_COUNT_QUERY.setIri("p", entityToDescribe.toStringID()); 078 } 079 080 /** 081 * Declare the property for which axiom(s) will be computed. 082 * 083 * @param property the property 084 */ 085 public void setPropertyToDescribe(S property) { 086 setEntityToDescribe(property); 087 } 088 089 /** 090 * @param strictOWLMode the strictOWLMode to set 091 */ 092 public void setStrictOWLMode(boolean strictOWLMode) { 093 this.strictOWLMode = strictOWLMode; 094 } 095 096 @Override 097 protected ParameterizedSparqlString getSampleQuery(){ 098 return GET_SAMPLE_QUERY; 099 } 100 101 /* (non-Javadoc) 102 * @see org.dllearner.core.AbstractAxiomLearningAlgorithm#learnAxioms() 103 */ 104 @Override 105 protected void learnAxioms() { 106 run(); 107 } 108 109 protected int getPropertyPopularity(){ 110 return getCountValue(COUNT_QUERY.toString()); 111 } 112 113 protected int getPropertyPopularity(Model model){ 114 return getCountValue(COUNT_QUERY.toString(), model); 115 } 116 117 protected int getDistinctSubjectsFrequency(){ 118 return getCountValue(DISTINCT_SUBJECTS_COUNT_QUERY.toString()); 119 } 120 121 protected int getDistinctObjectsFrequency(){ 122 return getCountValue(DISTINCT_OBJECTS_COUNT_QUERY.toString()); 123 } 124 125 protected int getCountValue(String query){ 126 ResultSet rs = executeSelectQuery(query); 127 return rs.next().getLiteral("cnt").getInt(); 128 } 129 130 /** 131 * Return the integer value of a SPARQL query that just returns a single COUNT value. 132 * It is assumed the the variable of the COUNT value is ?cnt. 133 * @param query the SPARQL query 134 * @param model the model containing the data 135 * @return the count value 136 */ 137 protected int getCountValue(String query, Model model){ 138 ResultSet rs = executeSelectQuery(query, model); 139 return rs.next().getLiteral("cnt").getInt(); 140 } 141 142 /** 143 * Compute the score of the axiom: 144 * 145 * @param cntA |A| 146 * @param cntB |B| 147 * @param cntAB |A AND B| 148 * @return 149 */ 150 protected AxiomScore computeScore(int cntA, int cntB, int cntAB) { 151 // precision (A AND B)/B 152 double precision = Heuristics.getConfidenceInterval95WaldAverage(cntB, cntAB); 153 154 // in the simplest case, the precision is our score 155 double score = precision; 156 157 // if enabled consider also recall and use F-score 158 if(!useSimpleScore ) { 159 // recall (A AND B)/A 160 double recall = Heuristics.getConfidenceInterval95WaldAverage(cntA, cntAB); 161 162 // F score 163 score = Heuristics.getFScore(recall, precision, beta); 164 } 165 166 int nrOfNegExamples = cntA - cntAB; 167 168 return new AxiomScore(score, score, cntAB, nrOfNegExamples, useSampling); 169 } 170 171 /** 172 * Whether to use only Precision or F-Measure. 173 * 174 * @param usePrecisionOnly 175 */ 176 public void setUsePrecisionOnly(boolean usePrecisionOnly) { 177 this.useSimpleScore = usePrecisionOnly; 178 } 179 180 protected abstract void run(); 181 182}