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.refinementoperators; 020 021import org.dllearner.core.ComponentAnn; 022import org.dllearner.core.ComponentInitException; 023import org.dllearner.core.config.ConfigOption; 024import org.dllearner.utilities.owl.OWLClassExpressionLengthMetric; 025import org.dllearner.utilities.owl.OWLClassExpressionUtils; 026import org.semanticweb.owlapi.model.OWLClassExpression; 027import uk.ac.manchester.cs.owl.owlapi.OWLObjectComplementOfImpl; 028 029import java.util.List; 030import java.util.Set; 031import java.util.TreeSet; 032 033/** 034 * The class uses an existing refinement operator and inverts it, i.e. a 035 * downward refinement operator is turned into an upward refinement operator 036 * and vice versa. 037 * 038 * @author Jens Lehmann 039 * 040 */ 041@ComponentAnn(name = "OperatorInverter", shortName = "inv_op", version = 0.1) 042public class OperatorInverter extends AbstractRefinementOperator implements LengthLimitedRefinementOperator { 043 044 @ConfigOption(description = "class expression length calculation metric") 045 private OWLClassExpressionLengthMetric lengthMetric; 046 047 public LengthLimitedRefinementOperator getOperator() { 048 return operator; 049 } 050 051 public void setOperator(LengthLimitedRefinementOperator operator) { 052 this.operator = operator; 053 this.lengthMetric = operator.getLengthMetric(); 054 if (this.lengthMetric == null) { 055 this.lengthMetric = OWLClassExpressionLengthMetric.getDefaultMetric(); 056 } 057 } 058 059 public boolean isUseNegationNormalForm() { 060 return useNegationNormalForm; 061 } 062 063 public void setUseNegationNormalForm(boolean useNegationNormalForm) { 064 this.useNegationNormalForm = useNegationNormalForm; 065 } 066 067 public boolean isGuaranteeLength() { 068 return guaranteeLength; 069 } 070 071 public void setGuaranteeLength(boolean guaranteeLength) { 072 this.guaranteeLength = guaranteeLength; 073 } 074 075 @ConfigOption(description = "operator to invert", required = true) 076 private LengthLimitedRefinementOperator operator; 077 @ConfigOption(description = "whether to apply NNF", defaultValue = "true") 078 private boolean useNegationNormalForm = true; 079 @ConfigOption(description = "Whether inverse solutions must respect the desired max length", defaultValue = "true") 080 private boolean guaranteeLength = true; 081 082 public OperatorInverter(LengthLimitedRefinementOperator operator) { 083 this.operator = operator; 084 this.lengthMetric = operator.getLengthMetric(); 085 } 086 087 public OperatorInverter() { 088 } 089 090 @Override 091 public Set<OWLClassExpression> refine(OWLClassExpression description) { 092 Set<OWLClassExpression> refinements = operator.refine(getNegation(description)); 093 TreeSet<OWLClassExpression> results = new TreeSet<>(); 094 for(OWLClassExpression d : refinements) { 095 results.add(getNegation(d)); 096 } 097 return results; 098 } 099 100 @Override 101 public Set<OWLClassExpression> refine(OWLClassExpression description, int maxLength) { 102 OWLClassExpression negatedDescription = getNegation(description); 103// System.out.println("negated description: " + negatedDescription); 104 // concept length can change because of the conversion process; as a heuristic 105 // we increase maxLength by the length difference of negated and original concept 106 int lengthDiff = Math.max(0, OWLClassExpressionUtils.getLength(negatedDescription, lengthMetric) - OWLClassExpressionUtils.getLength(description, lengthMetric)); 107 Set<OWLClassExpression> refinements = operator.refine(negatedDescription, maxLength+lengthDiff+1); 108// System.out.println("refinv: " + refinements); 109 TreeSet<OWLClassExpression> results = new TreeSet<>(); 110 for(OWLClassExpression d : refinements) { 111 OWLClassExpression dNeg = getNegation(d); 112// System.out.println("dNeg: " + dNeg); 113 // to satisfy the guarantee that the method does not return longer 114 // concepts, we perform an additional check 115 if(!guaranteeLength || OWLClassExpressionUtils.getLength(dNeg, lengthMetric) <= maxLength) { 116 results.add(dNeg); 117 } 118 } 119 return results; 120 } 121 122 @Override 123 public Set<OWLClassExpression> refine(OWLClassExpression description, int maxLength, 124 List<OWLClassExpression> knownRefinements) { 125 throw new Error("Method not implemented."); 126 } 127 128 @Override 129 public void setLengthMetric(OWLClassExpressionLengthMetric lengthMetric) { 130 this.lengthMetric = lengthMetric; 131 operator.setLengthMetric(lengthMetric); 132 } 133 134 @Override 135 public OWLClassExpressionLengthMetric getLengthMetric() { 136 return this.lengthMetric; 137 } 138 139 private OWLClassExpression getNegation(OWLClassExpression description) { 140 OWLClassExpression negatedDescription = new OWLObjectComplementOfImpl(description); 141 if(useNegationNormalForm) { 142 negatedDescription = negatedDescription.getNNF(); 143 } 144 return negatedDescription; 145 } 146 147 @Override 148 public void init() throws ComponentInitException { 149 initialized = true; 150 } 151 152}