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.dst; 020 021import java.util.List; 022 023import org.dllearner.algorithms.decisiontrees.dsttdt.dst.MassFunction; 024import org.dllearner.algorithms.decisiontrees.utils.*; 025 026/** 027 * A class for representing a BBA 028 * @author Giuseppe Rizzo 029 * 030 * @param <T> 031 */ 032public class MassFunction <T extends Comparable<? super T>> { 033 private List<T> frameOfDiscernement;//frame of Discernement 034 private List<List<T>> powerSet; 035 private double[] values; 036 037 038// public static void setFrameOfDiscernement(){ 039// 040// } 041// 042 /** 043 * Constructor 044 * @param set 045 */ 046 public MassFunction(List<T> set){ 047 frameOfDiscernement=set; 048 generatePowerSet(); 049 values= new double[powerSet.size()]; 050 051 } 052 /** 053 * method for generating the powerset of a frame Of Discernment 054 * @return 055 */ 056 public void generatePowerSet(){ 057 058 powerSet=Combination.findCombinations(frameOfDiscernement); 059 } 060 061 062 /** 063 * Returns the subset of a frame of discernment 064 * @return insieme potenza 065 */ 066 @SuppressWarnings({ "unchecked", "rawtypes", "unused" }) 067 public List<T>[] getSubsetsOfFrame(){ 068 List[] result= new List[powerSet.size()]; 069 int i=0; 070 for(List<T> elem:powerSet){ 071 072 result[i]=powerSet.get(i); 073 i++; 074 } 075 return result; 076 } 077 078 public List<T> getFrame(){ 079 return frameOfDiscernement; 080 081 } 082 /** 083 * Set a specific value for this BBA 084 */ 085 public void setValues(List<T> label,double value){ 086 int pos= SetUtils.find(label,powerSet); 087 values[pos]=value; 088 089 090 } 091 092 093 /** 094 * Returns the value of a BBA for a specific element of class 095 * @param label 096 * @return the value of a bba or NaN 097 */ 098 public double getValue(List<T> label){ 099 //System.out.println(valori.get(categoria)); 100 int pos= SetUtils.find(label, powerSet); 101 return values[pos]; 102 103 } 104 105 106 public double getNonSpecificityMeasureValue(){ 107 double result=0; 108 for(List<T> label: powerSet){ 109 if(!label.isEmpty()) 110 result+=(values[SetUtils.find(label, powerSet)]*Math.log(label.size())); 111 } 112// System.out.println("Non-sp: "+result); 113 return result; 114 } 115 116 117 public double getRandomnessMeasure(){ 118 double result=0.0; 119 for (List<T> c: powerSet){ 120 double pignisticValue=getPignisticTransformation(c); 121 int posCategoria = SetUtils.find(c, powerSet); 122 result+= -1* (values[posCategoria]*Math.log(pignisticValue)); 123 124 } 125 return result; 126 127 128 129 } 130 131 public double getPignisticTransformation(List<T> cl){ 132 // it works certainly for {-1,+1} as a frame of discernement 133 double result=0.0; 134 for(T element: cl){ 135 double pignisticValueForElement=0; // initialization 136 for(List<T> categoria: powerSet){ 137 138 if(!categoria.isEmpty()){ 139 if (categoria.contains(element)){ 140 int posCategoria = SetUtils.find(categoria, powerSet); 141 pignisticValueForElement += values[posCategoria]/categoria.size(); 142 } 143 } 144 145 } 146 result+=pignisticValueForElement; 147 148 } 149 return result; 150 } 151 152 153 public double getGlobalUncertaintyMeasure(){ 154 155 double nonSpecificity= this.getNonSpecificityMeasureValue(); 156 double randomness= this.getRandomnessMeasure(); 157 final double LAMBDA= 0.1; 158 double result= ((1-LAMBDA)*nonSpecificity)+(LAMBDA*randomness); 159 return result; 160 161 } 162 163 /** 164 * The method computes a confusion measure described in Smarandache et.al as discordant measure 165 * @return 166 */ 167 public double getConfusionMeasure(){ 168 double result=0; 169 for(List<T> labels: powerSet){ 170 if(!labels.isEmpty()) 171 result-=(values[SetUtils.find(labels, powerSet)]*Math.log(this.computeBeliefFunction(labels))); 172 } 173// System.out.println("Non-sp: "+result); 174 return result; 175 } 176 177 178 @SuppressWarnings({ "unchecked", "rawtypes" }) 179 /** 180 * combine two BBAs according to the Dempster rule 181 * @param function 182 * @return 183 */ 184 public MassFunction combineEvidences(MassFunction function){ 185 MassFunction result= new MassFunction(frameOfDiscernement); 186 double conflitto=getConflict(function); 187 188 for(List<T> elem:powerSet){ 189 int pos=SetUtils.find(elem, powerSet); 190 191 for(List<T>hypothesis1: powerSet){ 192 for(List<T>hypothesis2:powerSet){ 193 List<T> hypothesis12=SetUtils.intersection(hypothesis1, hypothesis2); 194 195 if(!(hypothesis12.isEmpty())&&(SetUtils.areEquals(hypothesis12, elem))){ 196 SetUtils.find(hypothesis1, powerSet); 197 SetUtils.find(hypothesis2, powerSet); 198 double massProduct=getValue(hypothesis1)*function.getValue(hypothesis2)/conflitto; 199 result.values[pos]+=massProduct; 200 201 } 202// System.out.println("Valori"+pos+"----"+result.valori[pos]); 203 } 204 205 } 206 207 208 } 209 210 return result; 211 212 } 213 214 215 216 217 218 219 220 /** 221 * Dempster rule for more BBAs 222 * @param function 223 * @return 224 */ 225 @SuppressWarnings("rawtypes") 226 public MassFunction combineEvidences(MassFunction... function){ 227 if(function.length==0) 228 throw new RuntimeException("At least a mass function is required"); 229 MassFunction result=this.combineEvidences(function[0]); 230 // associative operation 231 for(int i=1;i<function.length;i++){ 232 233 234 result= result.combineEvidences(function[i]); 235 236 } 237 238 239 240 241 return result; 242 243 } 244 245 /** 246 * Implementation of Dubois-Prade combination rule 247 * @param function 248 * @return 249 */ 250 @SuppressWarnings({ "unchecked", "rawtypes" }) 251 public MassFunction<T> combineEvidencesDuboisPrade (MassFunction function){ 252 253 MassFunction<T> result= new MassFunction(frameOfDiscernement); 254 255 // i-th hypothesis 256 for(List<T> elem:powerSet){ 257 int pos=SetUtils.find(elem, powerSet); 258 // intersection betwee 259 for(List<T>hypothesis1: powerSet){ 260 for(List<T>hypothesis2:powerSet){ 261 List<T> hypothesis12=SetUtils.union(hypothesis1, hypothesis2); 262 // 263 if((SetUtils.areEquals(hypothesis2, elem))){ 264 SetUtils.find(hypothesis1, powerSet); 265 SetUtils.find(hypothesis2, powerSet); 266 double massProduct=getValue(hypothesis1)*function.getValue(hypothesis2); 267 result.values[pos]+=massProduct; 268 269 } 270 271 } 272 273 } 274// result.valori[pos]=result.valori[pos]; 275 276 } 277 278 return result; 279 280 } 281 282 @SuppressWarnings("rawtypes") 283 public MassFunction combineEvidencesDuboisPrade(MassFunction... function){ 284 if(function.length==0) 285 throw new RuntimeException("More than 1 mass function are required"); 286 MassFunction result=this.combineEvidencesDuboisPrade(function[0]); 287 // operative association 288 for(int i=1;i<function.length;i++) 289 result= result.combineEvidencesDuboisPrade(function[i]); 290 291 292 293 294 295 296 return result; 297 298 } 299 300 301 302 /** 303 * Compute the conflict between two hypotheses 304 * @param function 305 * @return 306 */ 307 @SuppressWarnings({ "rawtypes", "unchecked" }) 308 public double getConflict(MassFunction function){ 309 double emptyMass=0; 310 for(List<T> hypothesis:powerSet){ 311// System.out.println("***************"); 312// System.out.println("Ipotesi 1:"+ipotesi1); 313 for(List<T> hypothesis2:powerSet){ 314// System.out.println("Ipotesi 2:"+ipotesi2); 315 List<T>intersezione=SetUtils.intersection(hypothesis,hypothesis2); 316 if(!intersezione.isEmpty()){ 317// System.out.println("Intersezione vuota"); 318 emptyMass+= (getValue(hypothesis)*function.getValue(hypothesis2)); 319// System.out.println(massaVuota); 320 } 321 322 323 } 324 325 326 } 327 328 return (emptyMass); 329 } 330 /** 331 * Compute the belief function value 332 * @param hypothesis 333 * @return 334 */ 335 public double computeBeliefFunction(List<T> hypothesis){ 336 double bel_hypothesis=0; 337 for(List<T> elem:powerSet){ 338 // for all non-empty subsets 339 if(!elem.isEmpty()&& hypothesis.containsAll(elem)){ 340 // somma le masse 341// System.out.println("m("+elem+")="+bel_ipotesi); 342 bel_hypothesis+=getValue(elem); 343 344 } 345 } 346// System.out.println("Belief:"+bel_ipotesi); 347 348 return bel_hypothesis; 349 } 350 /** 351 * Compute the plausibility function value 352 * @param ipotesi 353 * @return 354 */ 355 public double calcolaPlausibilityFunction(List<T> ipotesi){ 356 // 357 double pl_ipotesi=0; 358 for(List<T> elem:powerSet){ 359 360 if(!(SetUtils.intersection(ipotesi,elem)).isEmpty()) 361 362 pl_ipotesi+=getValue(elem); 363// System.out.println(pl_ipotesi); 364 } 365 366// System.out.println("Plausibility"+pl_ipotesi); 367 return pl_ipotesi; 368 369 370 } 371 /** 372 * Computation of the confirmation function 373 * @param ipotesi 374 * @return 375 */ 376 public double getConfirmationFunctionValue(List<T>ipotesi){ 377 return (computeBeliefFunction(ipotesi)+calcolaPlausibilityFunction(ipotesi)-1); 378 379 } 380 381 public String toString(){ 382 String res=""; 383 for(int i=0;i<powerSet.size();i++){ 384 String string = ""+powerSet.get(i)+values[i]; 385 res+= string; 386 } 387 return res; 388 } 389 390 391 392 393 394 395} 396