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.decisiontrees.tdt.model; 020 021import java.util.ArrayList; 022import java.util.HashSet; 023import java.util.List; 024import java.util.Set; 025import java.util.Stack; 026 027//import knowledgeBasesHandler.KnowledgeBase; 028 029import org.semanticweb.owlapi.model.OWLClass; 030import org.semanticweb.owlapi.model.OWLClassExpression; 031import org.semanticweb.owlapi.model.OWLDataFactory; 032 033import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl; 034 035public class DLTree extends AbstractTree { 036 037 private int match, omission, commission, induction; 038 039 /* (non-Javadoc) 040 * @see algorithms.trees.models.AbstractTree#getMatch() 041 */ 042 @Override 043 public int getMatch() { 044 return match; 045 } 046 047 /* (non-Javadoc) 048 * @see algorithms.trees.models.AbstractTree#setMatch(int) 049 */ 050 @Override 051 public void setMatch(int match) { 052 this.match++; 053 } 054 055 /* (non-Javadoc) 056 * @see algorithms.trees.models.AbstractTree#getOmission() 057 */ 058 @Override 059 public int getOmission() { 060 return omission; 061 } 062 063 /* (non-Javadoc) 064 * @see algorithms.trees.models.AbstractTree#setOmission(int) 065 */ 066 @Override 067 public void setOmission(int omission) { 068 this.omission++; 069 } 070 071 /* (non-Javadoc) 072 * @see algorithms.trees.models.AbstractTree#getCommission() 073 */ 074 @Override 075 public int getCommission() { 076 return commission; 077 } 078 079 /* (non-Javadoc) 080 * @see algorithms.trees.models.AbstractTree#setCommission(int) 081 */ 082 @Override 083 public void setCommission(int commission) { 084 this.commission++; 085 } 086 087 /* (non-Javadoc) 088 * @see algorithms.trees.models.AbstractTree#getInduction() 089 */ 090 @Override 091 public int getInduction() { 092 return induction; 093 } 094 095 /* (non-Javadoc) 096 * @see algorithms.trees.models.AbstractTree#setInduction(int) 097 */ 098 @Override 099 public void setInduction(int induction) { 100 this.induction++; 101 } 102 int nFoglie; 103 private class DLNode { 104 105 OWLClassExpression concept; // node concept 106 DLTree pos; // positive decision subtree 107 DLTree neg; // negative decision subtree 108 109 public DLNode(OWLClassExpression c) { 110 concept = c; 111 this.pos = this.neg = null; // node has no children 112 } 113 114 // public DLNode() { 115 // concept = null; 116 //// this.pos = this.neg = null; // node has no children 117 // } 118 119 public String toString() { 120 return this.concept.toString(); 121 } 122 123 } 124 125 private DLNode root; // Tree root 126 127 public DLTree () { 128 this.root = null; 129 } 130 131 public DLTree (OWLClassExpression c) { 132 this.root = new DLNode(c); 133 } 134 135 /** 136 * @param concept the root concept to set 137 */ 138 public void setRoot(OWLClassExpression concept) { 139 this.root = new DLNode(concept); 140 // this.root.concept = concept; 141 } 142 143 /** 144 * @return the root 145 */ 146 public OWLClassExpression getRoot() { 147 return root.concept; 148 } 149 150 public void setPosTree(DLTree subTree) { 151 this.root.pos = subTree; 152 153 } 154 155 public void setNegTree(DLTree subTree) { 156 157 this.root.neg = subTree; 158 159 } 160 161 public String toString() { 162// if (root==null) 163// return null; 164// if (root.pos == null && root.neg == null) 165// return root.toString(); 166// else 167// return root.concept.toString() + " ["+root.pos.toString()+" "+root.neg.toString()+"]"; 168 169 String string=""; 170 Stack<DLTree> stack= new Stack<>(); 171 stack.push(this); 172 DLTree currenttree=null; 173 while(!stack.isEmpty()){ 174 currenttree=stack.pop(); 175 string+= this.root.concept.toString(); // current node 176 if (root.pos != null) { 177 stack.push(root.pos); 178 string+="["; 179 } 180 if(root.neg != null){ 181 stack.push(root.neg); 182 string+="]"; 183 } 184 185 186 } 187 return string; 188 189 } 190 191 public DLTree getPosSubTree() { 192 return root.pos; 193 } 194 195 public DLTree getNegSubTree() { 196 197 return root.neg; 198 } 199 200 private double getNodes(){ 201 202 ArrayList<DLNode> list = new ArrayList<>(); 203 double num=0; 204 if(root!=null){ 205 list.add(root); 206 while(!list.isEmpty()){ 207 DLNode node= list.get(0); 208 list.remove(0); 209 num++; 210 DLNode sx=null; 211 if(node.pos!=null){ 212 sx= node.pos.root; 213 if(sx!=null) 214 list.add(sx); 215 } 216 if(node.neg!=null){ 217 sx= node.neg.root; 218 if(sx!=null) 219 list.add(sx); 220 } 221 222 } 223 224 } 225 226 return num; 227 228 } 229 230 @Override 231 public double getComplexityMeasure() { 232 // TODO Auto-generated method stub 233 return getNodes(); 234 } 235 236 public List<DLTree> getLeaves(){ 237 ArrayList<DLTree> leaves= new ArrayList<>(); 238 239 ArrayList<DLTree> list = new ArrayList<>(); 240 241 if(root!=null){ 242 list.add(this); 243 while(!list.isEmpty()){ 244 DLTree current= list.get(0); 245 list.remove(0); 246 if ((current.getPosSubTree()==null)&&(current.getNegSubTree()==null)) 247 leaves.add(current); 248 249 else{ 250 if(current.getPosSubTree()!=null) 251 list.add(current.getPosSubTree()); 252 253 if (current.getNegSubTree()!=null) 254 list.add(current.getNegSubTree()); 255 } 256 } 257 258 } 259 260 return leaves; 261 262 } 263 264 private static void associate(DLTree tree, OWLDataFactory df, OWLClass leaf, OWLClassExpression currentConceptDescription, Set<OWLClassExpression> set){ 265 266 if ((tree.root.pos==null)&&(tree.root.neg==null)){ 267 if (tree.root.concept.compareTo(leaf)==0){ 268 269 set.add(currentConceptDescription); 270 } 271 } 272 else{ 273 //OWLDataFactory dataFactory = new OWLDataFactoryImpl(); 274 // tail recursive calls 275 associate(tree.getPosSubTree(),df,leaf, df.getOWLObjectIntersectionOf(currentConceptDescription, tree.root.concept),set); 276 associate(tree.getNegSubTree(),df, leaf, df.getOWLObjectIntersectionOf(currentConceptDescription, tree.root.concept),set); 277 } 278 279 } 280 281 /** 282 * Return a concept definition from a DLTree (both the positive and the negative instances) 283 * @param tree 284 * @param conceptFromPositiveIstances 285 * @return 286 */ 287 public static OWLClassExpression deriveDefinition(DLTree tree, boolean conceptFromPositiveIstances){ 288 289 HashSet<OWLClassExpression> exp= new HashSet<>(); 290 291 OWLDataFactory dataFactory = new OWLDataFactoryImpl(); 292 if (conceptFromPositiveIstances) 293 associate(tree, dataFactory, dataFactory.getOWLThing(), dataFactory.getOWLThing(), exp); 294 else 295 associate(tree, dataFactory, dataFactory.getOWLNothing(), dataFactory.getOWLThing(), exp); 296 if(exp.isEmpty()) 297 return dataFactory.getOWLThing(); 298 else 299 return dataFactory.getOWLObjectUnionOf(exp); 300 301 } 302 303}