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.dsttdt;
020
021import java.util.ArrayList;
022//import knowledgeBasesHandler.KnowledgeBase;
023import java.util.List;
024import java.util.Set;
025import java.util.SortedSet;
026import java.util.Stack;
027import java.util.TreeSet;
028
029import org.dllearner.algorithms.decisiontrees.dsttdt.dst.MassFunction;
030import org.dllearner.algorithms.decisiontrees.dsttdt.models.DSTDLTree;
031import org.dllearner.algorithms.decisiontrees.dsttdt.models.EvidentialModel;
032import org.dllearner.algorithms.decisiontrees.heuristics.TreeInductionHeuristics;
033import org.dllearner.algorithms.decisiontrees.refinementoperators.DLTreesRefinementOperator;
034import org.dllearner.algorithms.decisiontrees.utils.Couple;
035import org.dllearner.algorithms.decisiontrees.utils.Npla;
036import org.dllearner.algorithms.decisiontrees.utils.Split;
037import org.dllearner.core.AbstractCELA;
038import org.dllearner.core.AbstractClassExpressionLearningProblem;
039import org.dllearner.core.AbstractReasonerComponent;
040import org.dllearner.core.ComponentAnn;
041import org.dllearner.core.ComponentInitException;
042import org.dllearner.core.EvaluatedDescription;
043import org.dllearner.core.annotations.OutVariable;
044import org.dllearner.core.annotations.Unused;
045import org.dllearner.core.config.ConfigOption;
046import org.dllearner.learningproblems.PosNegUndLP;
047import org.dllearner.refinementoperators.RefinementOperator;
048import org.semanticweb.owlapi.model.OWLClassExpression;
049import org.semanticweb.owlapi.model.OWLIndividual;
050import org.slf4j.Logger;
051import org.slf4j.LoggerFactory;
052
053@ComponentAnn(name="ETDT", shortName="etdt", version=1.0, description="An Evidence-based Terminological Decision Tree")
054public class DSTTDTClassifier extends AbstractCELA{
055        
056        //static final double THRESHOLD = 0.05;
057        //static final double M = 3;
058        private static Logger logger= LoggerFactory.getLogger(DSTTDTClassifier.class);
059        
060        @OutVariable
061        private DSTDLTree currentmodel; // model induced from the procedure
062        private boolean stop;
063        
064        @Unused
065        protected OWLClassExpression classToDescribe; //target concept
066        @ConfigOption(description = "instance of heuristic to use", defaultValue = "TreeInductionHeuristics")
067        protected TreeInductionHeuristics heuristic; // heuristic
068        //protected LengthLimitedRefinementOperator operator ;// refinement operator
069
070        @ConfigOption(description = "refinement operator instance to use", defaultValue = "DLTreesRefinementOperator")
071        protected RefinementOperator operator;
072
073        //private KnowledgeBase kb;
074        public DSTTDTClassifier() {
075                //this.kb=kb;
076                super();
077        }
078
079        public DSTTDTClassifier(AbstractClassExpressionLearningProblem problem, AbstractReasonerComponent reasoner) {
080                super(problem, reasoner);
081                //              configurator = new CELOEConfigurator(this);
082        }
083        
084        @ConfigOption(defaultValue = "0.05", description = "Purity threshold for setting a leaf")
085        protected  double puritythreshold;
086
087        @ConfigOption(defaultValue = "4", description = "value for limiting the number of generated concepts")
088        protected int  beam;
089        
090        
091        @ConfigOption(defaultValue = "false", description = "a flag to decide if further control on the purity measure should be made")
092        protected boolean nonSpecifityControl;
093        
094
095        public boolean isNonSpecifityControl() {
096                return nonSpecifityControl;
097        }
098
099        public void setNonSpecifityControl(boolean nonSpecifityControl) {
100                this.nonSpecifityControl = nonSpecifityControl;
101        }
102
103        //@ConfigOption(defaultValue = "false", description = "for overcoming the problem of missing values in tree algorithms.tree.models")
104        //protected boolean missingValueTreatmentForTDT;
105        protected double prPos;
106        protected double prNeg;
107        //protected OWLClassExpression classToDescribe; //target concept
108        //protected DLTreeHeuristics heuristic; // heuristic
109        //protected LengthLimitedRefinementOperator operator ;// refinement operator
110
111        //protected RefinementOperator operator;
112
113        public double getPuritythreshold() {
114                return puritythreshold;
115        }
116
117        public void setPuritythreshold(double puritythreshold) {
118                this.puritythreshold = puritythreshold;
119        }
120
121        public int getBeam() {
122                return beam;
123        }
124
125        public void setBeam(int beam) {
126                this.beam = beam;
127        }
128
129//      public boolean isBinaryClassification() {
130//              return binaryClassification;
131//      }
132//
133//
134//      public void setBinaryClassification(boolean binaryClassification) {
135//              this.binaryClassification = binaryClassification;
136//      }
137
138        public OWLClassExpression getClassToDescribe() {
139                return classToDescribe;
140        }
141
142        public void setClassToDescribe(OWLClassExpression classToDescribe) {
143                this.classToDescribe = classToDescribe;
144        }
145
146        public TreeInductionHeuristics getHeuristic() {
147                return heuristic;
148        }
149
150        public void setHeuristic(TreeInductionHeuristics heuristic) {
151                this.heuristic = heuristic;
152        }
153
154        public RefinementOperator getOperator() {
155                return operator;
156        }
157
158        public void setOperator(RefinementOperator operator) {
159                this.operator = operator;
160        }
161
162        @Override
163        public void init() throws ComponentInitException{
164                //inizialization
165                
166                // TODO Auto-generated method stub
167                                baseURI = reasoner.getBaseURI();
168                                prefixes = reasoner.getPrefixes();
169
170                                // if no one injected a heuristic, we use a default one
171                                if(heuristic == null) {
172                                        heuristic = new TreeInductionHeuristics();
173                                        heuristic.setProblem(learningProblem);
174                                        heuristic.setReasoner(reasoner);
175
176                                        heuristic.init();
177                                }
178
179                                if(operator == null) {
180                                        // default operator
181                                        operator= new DLTreesRefinementOperator((PosNegUndLP)super.learningProblem, getReasoner(), 4);
182                                        //operator = new DLTreesRefinementOperator( this.learningProblem,reasoner,4);
183                                        ((DLTreesRefinementOperator)operator).setReasoner(reasoner);
184                                        ((DLTreesRefinementOperator)operator).setBeam(4); // default value
185                                        //System.out.println("Refinement operator"+operator);
186                                        
187//                                      if(operator instanceof CustomStartRefinementOperator) {
188//                                              ((CustomStartRefinementOperator)operator).setStartClass(startClass);
189//                                      }
190//                                      if(operator instanceof ReasoningBasedRefinementOperator) {
191//                                              ((ReasoningBasedRefinementOperator)operator).setReasoner(reasoner);
192//                                      }
193                                        operator.init();
194                                
195                                        
196                                
197                                }
198
199                                //start();
200
201                initialized = true;
202        }
203        
204        
205        
206        
207        @SuppressWarnings({ "unchecked", "rawtypes" })
208        public DSTDLTree induceDSTDLTree
209        (SortedSet<OWLIndividual> posExs, SortedSet<OWLIndividual> negExs,      SortedSet<OWLIndividual> undExs) {
210                
211
212                Npla<SortedSet<OWLIndividual>,SortedSet<OWLIndividual>,SortedSet<OWLIndividual>, Integer, Double, Double> examples = new Npla<>(posExs, negExs, undExs, beam, prPos, prNeg);
213                DSTDLTree tree = new DSTDLTree(); // new (sub)tree
214                Stack<Couple<DSTDLTree,Npla<SortedSet<OWLIndividual>,SortedSet<OWLIndividual>,SortedSet<OWLIndividual>, Integer, Double, Double>>> stack= new Stack<>();
215                Couple<DSTDLTree,Npla<SortedSet<OWLIndividual>,SortedSet<OWLIndividual>,SortedSet<OWLIndividual>, Integer, Double, Double>> toInduce= new Couple<>();
216                toInduce.setFirstElement(tree);
217                toInduce.setSecondElement(examples);
218                stack.push(toInduce);
219
220                Stack<DSTDLTree> lastTrees= new Stack<>(); // for refine hierarchically a concept
221                while (!stack.isEmpty()){
222
223                        // pop from the stack
224                        Couple<DSTDLTree,Npla<SortedSet<OWLIndividual>,SortedSet<OWLIndividual>,SortedSet<OWLIndividual>, Integer, Double, Double>> current= stack.pop(); // extract the next element
225                        Npla<SortedSet<OWLIndividual>, SortedSet<OWLIndividual>,SortedSet<OWLIndividual>, Integer, Double, Double> currentExamples= current.getSecondElement();
226                        // set of negative, positive and undefined example
227                        posExs=currentExamples.getFirst();
228                        negExs=currentExamples.getSecond();
229                        undExs=currentExamples.getThird();
230                        DSTDLTree currentTree= current.getFirstElement();
231                        //System.out.println("Current Tree: "+ (currentTree==null));
232                        int psize = posExs.size();
233                        int nsize = negExs.size();
234                        int usize = undExs.size();
235                        System.out.printf("Learning problem\t p:%d\t n:%d\t u:%d\t prPos:%4f\t prNeg:%4f\n",
236                                        psize, nsize, usize, prPos, prNeg);
237
238                        //build the BBA for the current node
239                        ArrayList<Integer> frame = new ArrayList<>();
240                        frame.add(-1);
241                        frame.add(1);
242                        MassFunction mass= new MassFunction(frame);
243                        ArrayList<Integer> positive= new ArrayList<>();
244                        positive.add(1);
245                        double positiveValue = (double)psize/(psize+ nsize+usize);
246                        if( (psize+ nsize+usize)==0){
247                                positiveValue= prPos;
248                        }
249                        mass.setValues(positive, positiveValue);
250                        ArrayList<Integer> negative= new ArrayList<>();
251                        negative.add(-1);
252                        double negativeValue = (double)nsize/(psize+ nsize+usize);
253                        if( (psize+ nsize+usize)==0){
254                                negativeValue= prNeg;
255                        }
256                        mass.setValues(negative, negativeValue);
257                        double undValue = ((double)usize/(psize+ nsize+usize));
258
259                        if( (psize+ nsize+usize)==0){
260                                undValue= 0;
261                        }
262                        mass.setValues(frame, undValue);
263                        
264
265                        //      System.out.println("MASS: "+ positiveValue +", "+negativeValue+", "+undValue);
266                        //  ragionamento sui prior
267
268                        if (psize == 0 && nsize == 0) // no exs
269                                if (prPos >= prNeg) {
270                                        // prior majority of positives
271                                        currentTree.setRoot(dataFactory.getOWLThing(), mass); // set positive leaf
272                                        //                                      return tree;
273                                }
274                                else { // prior majority of negatives
275                                        currentTree.setRoot(dataFactory.getOWLNothing(),mass); // set negative leaf
276                                        //                                      return tree;
277                                }
278                        else{
279                                //      double numPos = posExs.size() + undExs.size()*prPos;
280                                //      double numNeg = negExs.size() + undExs.size()*prNeg;
281                                double numPos = psize;
282                                double numNeg = nsize;
283                                double perPos = numPos/(numPos+numNeg);
284                                double perNeg = numNeg/(numPos+numNeg);
285                                if (perNeg==0 && perPos > puritythreshold) { // no negative
286                                        //                      System.out.println("Thing as leaf");
287                                        currentTree.setRoot(dataFactory.getOWLThing(), mass); // set positive lea
288                                        //                              return tree;
289                                }
290                                else if (perPos==0 && perNeg > puritythreshold) { // no positive
291                                        //                              System.out.println("NoThing as leaf");
292                                        currentTree.setRoot(dataFactory.getOWLNothing(), mass); // set negative leaf
293                                        //                                      return tree;
294                                }
295                                else{
296                                        //System.out.println("Non specificity: "+nonSpecifityControl);
297                                        if (!nonSpecifityControl){
298                                                //OWLClassExpression[] cConcepts= new OWLClassExpression[0];
299                                                DLTreesRefinementOperator dlTreesRefinementOperator = (DLTreesRefinementOperator)operator;
300                                                
301                                                //System.out.println("is null?: "+dlTreesRefinementOperator==null);
302                                                Set<OWLClassExpression> refine = null;
303                                                                if (lastTrees.isEmpty()){
304                                                                        refine = dlTreesRefinementOperator.refine(dataFactory.getOWLThing(), posExs, negExs);
305                                                                }
306                                                                else
307                                                                        refine = dlTreesRefinementOperator.refine(lastTrees.pop().getRoot(), posExs, negExs);
308                                                        
309                                                                
310                                                        //      dlTreesRefinementOperator.refine(dataFactory.getOWLThing(), posExs, negExs);
311                                                                System.out.println("Refinement:"+refine);
312                                                                
313                                                        ArrayList<OWLClassExpression> generateNewConcepts = new ArrayList<>(refine); // a generic refinement operator
314                                                        OWLClassExpression[] cConcepts = new OWLClassExpression[generateNewConcepts.size()];
315                                                        
316                                                        cConcepts= generateNewConcepts.toArray(cConcepts);
317                                                        
318                                                        //      OWLClassExpression[] cConcepts = allConcepts;
319
320                                                // select node couoncept
321                                                Couple<OWLClassExpression,MassFunction> newRootConcept = null;
322                                                if  (dlTreesRefinementOperator.getRo() ==DLTreesRefinementOperator.ORIGINAL) // 3: the original refinement operator for terminological trees
323                                                        newRootConcept= heuristic.selectBestConceptDST(cConcepts, posExs, negExs, undExs, prPos, prNeg);
324                                                else
325                                                        newRootConcept= heuristic.selectWorstConceptDST(cConcepts, posExs, negExs, undExs, prPos, prNeg);                       MassFunction refinementMass = newRootConcept.getSecondElement();
326
327                                                //System.out.println(newRootConcept.getFirstElement()+"----"+refinementMass);
328                                                SortedSet<OWLIndividual> posExsT = new TreeSet<>();
329                                                SortedSet<OWLIndividual> negExsT = new TreeSet<>();
330                                                SortedSet<OWLIndividual> undExsT = new TreeSet<>();
331                                                SortedSet<OWLIndividual> posExsF = new TreeSet<>();
332                                                SortedSet<OWLIndividual> negExsF = new TreeSet<>();
333                                                SortedSet<OWLIndividual> undExsF = new TreeSet<>();
334
335                                                Split.split(newRootConcept.getFirstElement(), dataFactory, reasoner, posExs, negExs, undExs, posExsT, negExsT, undExsT, posExsF, negExsF, undExsF);
336                                                // select node concept
337
338                                                currentTree.setRoot(newRootConcept.getFirstElement(), refinementMass);
339
340                                                //      undExsT = union(undExsT,
341                                                //                                              tree.setPosTree(induceDSTDLTree(posExsT, negExsT, undExsT, dim, prPos, prNeg));
342                                                //                                              tree.setNegTree(induceDSTDLTree(posExsF, negExsF, undExsF, dim, prPos, prNeg));
343
344                                                DSTDLTree posTree= new DSTDLTree();
345                                                DSTDLTree negTree= new DSTDLTree(); // recursive calls simulation
346                                                currentTree.setPosTree(posTree);
347                                                currentTree.setNegTree(negTree);
348                                                Npla<SortedSet<OWLIndividual>, SortedSet<OWLIndividual>, SortedSet<OWLIndividual>, Integer, Double, Double> npla1 = new Npla<>(posExsT, negExsT, undExsT, beam, perPos, perNeg);
349                                                Npla<SortedSet<OWLIndividual>, SortedSet<OWLIndividual>,SortedSet<OWLIndividual>, Integer, Double, Double> npla2 = new Npla<>(posExsF, negExsF, undExsF, beam, perPos, perNeg);
350                                                Couple<DSTDLTree,Npla<SortedSet<OWLIndividual>, SortedSet<OWLIndividual>,SortedSet<OWLIndividual>, Integer, Double, Double>> pos= new Couple<>();
351                                                pos.setFirstElement(posTree);
352                                                pos.setSecondElement(npla1);
353                                                // negative branch
354                                                Couple<DSTDLTree,Npla<SortedSet<OWLIndividual>, SortedSet<OWLIndividual>,SortedSet<OWLIndividual>, Integer, Double, Double>> neg= new Couple<>();
355                                                neg.setFirstElement(negTree);
356                                                neg.setSecondElement(npla2);
357                                                stack.push(neg);
358                                                stack.push(pos);
359                                                lastTrees.push(currentTree);
360
361                                        }
362                                        else if(mass.getNonSpecificityMeasureValue()<0.1){
363                                                //System.out.println();
364                                                DLTreesRefinementOperator dlTreesRefinementOperator = (DLTreesRefinementOperator)operator;
365                                                
366                                                //System.out.println("is null?: "+dlTreesRefinementOperator==null);
367                                                //Set<OWLClassExpression>
368                                                
369                                                //refine = dlTreesRefinementOperator.refine(dataFactory.getOWLThing(), posExs, negExs);
370                                                Set<OWLClassExpression> refine = null;
371                                                if (lastTrees.isEmpty()){
372                                                        refine = dlTreesRefinementOperator.refine(dataFactory.getOWLThing(), posExs, negExs);
373                                                }
374                                                else
375                                                        refine = dlTreesRefinementOperator.refine(lastTrees.pop().getRoot(), posExs, negExs);
376                                
377                                                
378                                                //ArrayList<OWLClassExpression> exps=new ArrayList<OWLClassExpression>(operator.refine(OWL_THING));
379                                                OWLClassExpression[] cConcepts =  new OWLClassExpression[refine.size()]; // concept generation
380                                                cConcepts = refine.toArray(cConcepts);
381
382                                                // select node concept
383                                                Couple<OWLClassExpression,MassFunction> newRootConcept = null;
384                                                if  (dlTreesRefinementOperator.getRo() ==DLTreesRefinementOperator.ORIGINAL) // 3: the original refinement operator for terminological trees
385                                                        newRootConcept= heuristic.selectBestConceptDST(cConcepts, posExs, negExs, undExs, prPos, prNeg);
386                                                else
387                                                        newRootConcept= heuristic.selectWorstConceptDST(cConcepts, posExs, negExs, undExs, prPos, prNeg); // otherwise select the worst concept
388
389                                                //heuristic.selectBestConceptDST(cConcepts, posExs, negExs, undExs, prPos, prNeg);
390                                                MassFunction refinementMass = newRootConcept.getSecondElement();
391
392                                                //logger.debug(newRootConcept.getFirstElement()+"----"+refinementMass);
393                                                SortedSet<OWLIndividual> posExsT = new TreeSet<>();
394                                                SortedSet<OWLIndividual> negExsT = new TreeSet<>();
395                                                SortedSet<OWLIndividual> undExsT = new TreeSet<>();
396                                                SortedSet<OWLIndividual> posExsF = new TreeSet<>();
397                                                SortedSet<OWLIndividual> negExsF = new TreeSet<>();
398                                                SortedSet<OWLIndividual> undExsF = new TreeSet<>();
399
400                                                //split(newRootConcept.getFirstElement(), posExs, negExs, undExs, posExsT, negExsT, undExsT, posExsF, negExsF, undExsF);
401                                                Split.split(newRootConcept.getFirstElement(), dataFactory, reasoner, posExs, negExs, undExs, posExsT, negExsT, undExsT, posExsF, negExsF, undExsF);
402                                                // select node concept
403
404                                                //tree.setRoot(newRootConcept.getFirstElement(), refinementMass);
405                                                currentTree.setRoot(newRootConcept.getFirstElement(), refinementMass);
406                                                //      undExsT = union(undExsT,
407                                                //                                              tree.setPosTree(induceDSTDLTree(posExsT, negExsT, undExsT, dim, prPos, prNeg));
408                                                //                                              tree.setNegTree(induceDSTDLTree(posExsF, negExsF, undExsF, dim, prPos, prNeg));
409
410                                                DSTDLTree posTree= new DSTDLTree();
411                                                DSTDLTree negTree= new DSTDLTree(); // recursive calls simulation through iteration
412                                                
413                                                
414                                                currentTree.setPosTree(posTree);
415                                                currentTree.setNegTree(negTree);
416                                                Npla<SortedSet<OWLIndividual>, SortedSet<OWLIndividual>, SortedSet<OWLIndividual>, Integer, Double, Double> npla1 = new Npla<>(posExsT, negExsT, undExsT, beam, perPos, perNeg);
417                                                Npla<SortedSet<OWLIndividual>, SortedSet<OWLIndividual>, SortedSet<OWLIndividual>, Integer, Double, Double> npla2 = new Npla<>(posExsF, negExsF, undExsF, beam, perPos, perNeg);
418                                                Couple<DSTDLTree,Npla<SortedSet<OWLIndividual>,SortedSet<OWLIndividual>,SortedSet<OWLIndividual>, Integer, Double, Double>> pos= new Couple<>();
419                                                pos.setFirstElement(posTree);
420                                                pos.setSecondElement(npla1);
421                                                // negative branch
422                                                Couple<DSTDLTree,Npla<SortedSet<OWLIndividual>,SortedSet<OWLIndividual>,SortedSet<OWLIndividual>, Integer, Double, Double>> neg= new Couple<>();
423                                                neg.setFirstElement(negTree);
424                                                neg.setSecondElement(npla2);
425                                                stack.push(neg);
426                                                stack.push(pos);
427                                                lastTrees.push(currentTree);
428                                        }else{
429
430                                                if (perPos > perNeg) { // no negative
431                                                        currentTree.setRoot(dataFactory.getOWLThing(), mass); // set positive leaf
432                                                        //                                      return tree;
433                                                }
434                                                else {// no positive
435                                                        currentTree.setRoot(dataFactory.getOWLNothing(), mass); // set negative leaf
436                                                        //                                      return tree;
437                                                }
438
439                                        }
440
441                                }
442                        }
443
444                }
445
446                currentmodel= tree;
447                stop=true;
448                return tree;
449        }
450
451        @SuppressWarnings({ "unchecked", "rawtypes" })
452        private void classifyExampleDST(List<Couple<Integer,MassFunction<Integer>>> list,OWLIndividual indTestEx, DSTDLTree tree) {
453
454                
455                //      System.out.println("BBA "+m);
456
457                Stack<DSTDLTree> stack= new Stack<>();
458                stack.push(tree);
459                
460                
461                //OWLDataFactory dataFactory = kb.getDataFactory();
462                while (!stack.isEmpty()){
463                        
464                        DSTDLTree currenttree=stack.pop();
465                        OWLClassExpression rootClass = currenttree.getRoot();
466                        MassFunction m= currenttree.getRootBBA();
467                if (rootClass.equals(dataFactory.getOWLThing())){
468                        //              System.out.println("Caso 1");
469                        Couple<Integer,MassFunction<Integer>> result= new Couple<>();
470                        result.setFirstElement(+1);
471                        result.setSecondElement(m);
472                        list.add(result);
473                        //              if(testConcepts!=null){
474                        //                      if(kb.getReasoner().hasType(kb.getIndividuals()[indTestEx], testConcepts[0]))
475                        //                              tree.addPosExample(indTestEx);
476                        //                      else if (kb.getReasoner().hasType(kb.getIndividuals()[indTestEx], dataFactory.getOWLObjectComplementOf(testConcepts[0])))
477                        //                              tree.addNegExample(indTestEx);
478                        //                      else{
479                        //                              tree.addPosExample(indTestEx);
480                        //                              tree.addNegExample(indTestEx);
481                        //                      }
482                        //              }
483                }
484                else if (rootClass.equals(dataFactory.getOWLNothing())){
485                        //              System.out.println("Caso 2");
486                        Couple<Integer,MassFunction<Integer>> result= new Couple<>();
487                        result.setFirstElement(-1);
488                        result.setSecondElement(m);
489                        list.add(result);
490
491                }
492                else if (reasoner.hasType(rootClass, indTestEx)){
493                        //System.out.println(kb.getReasoner().hasType(kb.getIndividuals()[indTestEx], rootClass));
494                        if (currenttree.getPosSubTree()!=null){
495
496//                              classifyExampleDST( list, indTestEx, tree.getPosSubTree());
497                                stack.push(currenttree.getPosSubTree());
498                                //                      System.out.println("------");
499                        }
500                        else{
501                                //                      System.out.println("Caso 4");
502                                Couple<Integer,MassFunction<Integer>> result= new Couple<>();
503                                result.setFirstElement(+1);
504                                result.setSecondElement(m);
505                                list.add(result);
506                                //                      System.out.println("ADdded");
507                        }
508                }
509                else if (reasoner.hasType(dataFactory.getOWLObjectComplementOf(rootClass), indTestEx)){
510                                //                      System.out.println(kb.getReasoner().hasType(kb.getIndividuals()[indTestEx], dataFactory.getOWLObjectComplementOf(rootClass)));
511                                if (currenttree.getNegSubTree()!=null){
512//                                      classifyExampleDST(list,indTestEx, tree.getNegSubTree());
513                                        stack.push(currenttree.getNegSubTree());
514                                        //                              System.out.println("#######");
515                                }
516                                else{
517                                        //                              System.out.println("Caso 6"+ tree);
518                                        Couple<Integer,MassFunction<Integer>> result= new Couple<>();
519                                        result.setFirstElement(-1);
520                                        result.setSecondElement(m);
521                                        list.add(result);
522                                        //                              System.out.println("ADdded");
523                                }
524                        }
525                        else{
526                                //follow both paths
527                                if (currenttree.getPosSubTree()!=null){
528                                        //                              System.out.println("Caso 7");
529
530//                                      classifyExampleDST(list, indTestEx, tree.getPosSubTree());
531                                        
532                                        stack.push(currenttree.getPosSubTree());
533                                }
534                                else{
535                                        //                              System.out.println("Caso 8");
536                                        Couple<Integer,MassFunction<Integer>> result= new Couple<>();
537                                        result.setFirstElement(+1);
538                                        result.setSecondElement(m);
539                                        list.add(result);
540                                        //                              System.out.println("ADdded");
541                                }
542                                //System.out.println("---->");
543                                if (currenttree.getNegSubTree()!=null){
544                                        //                              System.out.println("Caso 9");
545//                                      classifyExampleDST(list,indTestEx, tree.getNegSubTree());
546                                        stack.push(currenttree.getNegSubTree());
547                                }
548                                else{
549                                        Couple<Integer,MassFunction<Integer>> result= new Couple<>();
550                                        result.setFirstElement(-1);
551                                        result.setSecondElement(m);
552                                        list.add(result);
553                                        //                                      System.out.println("ADdded");
554                                }
555
556                        }
557
558                
559                }
560                //      System.out.println("Tree "+ tree);
561        }
562
563        public DSTDLTree getCurrentmodel() {
564                return currentmodel;
565        }
566
567        public void setCurrentmodel(DSTDLTree currentmodel) {
568                this.currentmodel = currentmodel;
569        }
570
571        @SuppressWarnings({ })
572        public int classifyExamplesDST(OWLIndividual indTestEx, DSTDLTree tree) {
573                //int length = testConcepts!=null?testConcepts.length:1;
574                //for (int c=0; c < length; c++) {
575                        MassFunction<Integer> bba = getBBA(indTestEx, tree); // to have a soft prediction
576                        int result= predict(bba);
577                         return  result;// belief or plausibility or confirmation function computation
578
579                //}
580        }
581
582        @SuppressWarnings({ "unchecked", "rawtypes" })
583        public MassFunction<Integer> getBBA(OWLIndividual indTestEx, EvidentialModel tree) {
584                // for now the method is not quite general for making predictions via other algorithms.tree.models, e.g. Evidential k-NN
585                
586                DSTDLTree model= (DSTDLTree) tree; // only classification with DST trees are supported for now
587                ArrayList<Couple<Integer, MassFunction<Integer>>> list;
588//              System.out.println("Tree \n"+ model);
589                list= new ArrayList<>();
590                classifyExampleDST(list,indTestEx, model);
591                // BBA from the reached leaves
592//              System.out.println("Lista di foglie");
593                //System.out.println(list);
594                MassFunction<Integer> bba=list.get(0).getSecondElement();
595
596                MassFunction<Integer>[] others= new MassFunction[(list.size()-1)];
597                //System.out.println("_____________BBA TO COMBINE______________________");
598                //System.out.println("BBA: "+bba);
599                for(int i=1; i<list.size();i++){
600                        MassFunction next=list.get(i).getSecondElement();
601//combination rule
602                        others[i-1]=next;
603                }
604                if(others.length>=1){
605                        bba=bba.combineEvidences(others);
606
607                }
608                return bba;
609        }
610
611        /**
612         * Implementation of forcing criterion for the final class assignement
613         * @param bba
614         */
615        private int predict(MassFunction<Integer> bba) {
616                ArrayList<Integer> hypothesis= new ArrayList<>();
617                hypothesis.add(+1);
618                double confirmationFunctionValuePos = bba.getConfirmationFunctionValue(hypothesis);
619                //                      double confirmationFunctionValuePos = bba.calcolaBeliefFunction(ipotesi);
620                // not concept
621                ArrayList<Integer> hypothesis2= new ArrayList<>();
622                hypothesis2.add(-1);
623                double confirmationFunctionValueNeg = bba.getConfirmationFunctionValue(hypothesis2);
624                //                      double confirmationFunctionValueNeg = bba.calcolaBeliefFunction(ipotesi2);
625                ArrayList<Integer> hypothesis3= new ArrayList<>();
626                hypothesis3.add(-1);
627                hypothesis3.add(+1);
628                double confirmationFunctionValueUnc = bba.getConfirmationFunctionValue(hypothesis3);
629                //                      double confirmationFunctionValueUnc = bba.calcolaBeliefFunction(ipotesi3);
630
631                //System.out.println(confirmationFunctionValuePos+ " vs. "+ confirmationFunctionValueNeg+ "vs." +confirmationFunctionValueUnc);
632
633                if((confirmationFunctionValueUnc>confirmationFunctionValuePos)&&(confirmationFunctionValueUnc>confirmationFunctionValueNeg))
634                        if (confirmationFunctionValuePos>confirmationFunctionValueNeg)
635                                 return +1;
636                        else if (confirmationFunctionValuePos<confirmationFunctionValueNeg)
637                                return -1;
638                        else return 0;
639                else if(confirmationFunctionValuePos>=confirmationFunctionValueNeg)
640                        return +1;
641                else
642                        return -1;
643
644                
645        }
646
647        @Override
648        public void start() {
649                // TODO Auto-generated method stub
650                
651                
652                PosNegUndLP learningProblem2 = (PosNegUndLP)learningProblem;
653                SortedSet<OWLIndividual> posExs = (SortedSet<OWLIndividual>)learningProblem2.getPositiveExamples();
654                SortedSet<OWLIndividual> negExs = (SortedSet<OWLIndividual>)learningProblem2.getNegativeExamples();
655                SortedSet<OWLIndividual> undExs = (SortedSet<OWLIndividual>)learningProblem2.getUncertainExamples();
656
657                //System.out.printf("--- Query Concept #%d \n",c);
658                
659                // the individuals of the ABox are the training individuals
660                //OWLIndividual[] trainingExs= reasoner.getIndividuals().toArray(new OWLIndividual[reasoner.getIndividuals().size()]);
661                //boolean binaryClassification= false; // when you use the evidential version of TDT model you must use only a ternary splitting
662                //Split.splitting(dataFactory, reasoner, trainingExs, posExs, negExs, undExs, classToDescribe, binaryClassification);
663
664                prPos = (double)posExs.size()/(posExs.size()+ negExs.size()+undExs.size());
665                prNeg = (double)negExs.size()/(posExs.size()+ negExs.size()+undExs.size());
666
667                //System.out.println("Training set composition: "+ posExs.size()+" - "+ negExs.size()+"-"+undExs.size());
668
669                double normSum = prPos+prNeg;
670                if (normSum==0) { prPos=.5;     prNeg=.5; }
671                else { prPos=prPos/normSum;     prNeg=prNeg/normSum; }
672
673                System.out.printf("New learning problem prepared.\n");
674                System.out.println("Learning a tree ");
675                  currentmodel= induceDSTDLTree(posExs, negExs, undExs);  // training procedure for induce a DSTTDT
676                
677                stop();
678
679                
680        }
681
682        @Override
683        public void stop() {
684                // TODO Auto-generated method stub
685                stop=true;
686        }
687
688        @Override
689        public boolean isRunning() {
690                // TODO Auto-generated method stub
691                return !(stop);
692        }
693
694        @Override
695        public OWLClassExpression getCurrentlyBestDescription() {
696                // TODO Auto-generated method stub
697                OWLClassExpression owlClassExpression = DSTDLTree.deriveDefinition(currentmodel, false);
698                return owlClassExpression;
699        }
700
701        @Override
702        public EvaluatedDescription getCurrentlyBestEvaluatedDescription() {
703                // TODO Auto-generated method stub
704                return null;
705        }
706
707        
708
709}