package trust.weka4jason;
import java.io.File;
import weka.classifiers.AbstractClassifier;
import weka.classifiers.Classifier;
import weka.classifiers.trees.J48;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.Utils;
import weka.core.converters.ArffLoader;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.Discretize;
/**
* This class contains the method for building a Tree Classifier that first bins data
* applying an unsupervised discretization filter, then applies the j48 algorithm to build
* the decision tree for the classification
* @author pc
*
*/
public class WekaBinClassifier extends WekaClassifier{
Discretize discretize;
/* working copy of the dataset with discretized class values */
WekaDataset discretizedDataset;
/* private object used for parsing */
private String[] class_bounds;
private double min, max;
public WekaBinClassifier(){
discretize = new Discretize();
super.classifier = new J48();
}
/**
* Valid options are:
-unset-class-temporarily
Unsets the class index temporarily before the filter is
applied to the data.
(default: no)
-B <num>
Specifies the (maximum) number of bins to divide numeric attributes into.
(default = 10)
-M <num>
Specifies the desired weight of instances per bin for
equal-frequency binning. If this is set to a positive
number then the -B option will be ignored.
(default = -1)
-F
Use equal-frequency instead of equal-width discretization.
-O
Optimize number of bins using leave-one-out estimate
of estimated entropy (for equal-width discretization).
If this is set then the -B option will be ignored.
-R <col1,col2-col4,...>
Specifies list of columns to Discretize. First and last are valid indexes.
(default: first-last)
-V
Invert matching sense of column indexes.
-D
Output binary attributes for discretized attributes.
*/
@Override
public void setWekaOptions(String weka_options){
try {
String[] options = Utils.splitOptions(weka_options);
discretize.setOptions(options);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Return a Decision tree built on the discretized set of scores and manifesta
* @param data: dataset
* @return Tree classifier
* @throws Exception
*/
public Classifier getClassifier() throws Exception{
//System.out.println("DATASET: "+dataset.getDataset());
//make a copy of the data set
discretizedDataset = (WekaDataset) dataset.clone();
//filter string attributes
discretizedDataset.nominalFilter();
Instances data = discretizedDataset.getDataset();
//safe check: no class attribute
data.setClassIndex(-1);
/*
* apply Discretize unsupervised filter
*/
discretize.setInputFormat(data);
data = Filter.useFilter(data, discretize);
//System.out.println("Filtered data:"+data);
//set class attribute
data.setClassIndex(data.numAttributes()-1);
discretizedDataset.setDataset(data);
/*
* build J48 classifier
*/
if(data.classAttribute().numValues()<2)
return null;
//System.out.println("dataset class index "+data.classIndex() + " "+data.classAttribute());
classifier.buildClassifier(data);
//System.out.println("dataset class index "+data.classIndex() + " "+data.classAttribute());
//System.out.println("\nDISCRETIZED DATASET: "+discretizedDataset.getDataset());
//System.out.println("Class index: "+discretizedDataset.getDataset().classIndex());
return classifier;
}
public AbstractClassifier getTree(){
return classifier;
}
public void testInstance(Instance instance) throws Exception{
//System.out.println(classifier);
instance.setDataset(discretizedDataset.getDataset());
double clsLabel = classifier.classifyInstance(instance);
instance.setClassValue(clsLabel);
}
public WekaDataset getWekaDiscretizedDataset(){
return discretizedDataset;
}
/**
* Receives as input the list of a given trustee manifesta and , on such a basis,
* tries to anticipate the result value of the possible delgation to that trustee
* <br/>
* usage is:<br/>
* <i>double trust = wekaBinClassifier.agentTrustEvuation(task, ability, disposition, cross);</i>
*/
@Override
public double agentTrustEvuation(Object... list) throws Exception {
Instance ag_entry = discretizedDataset.createNominalInstance(list);
if(ag_entry == null)
return 1;
else{
/* Set Dataset */
ag_entry.setDataset(discretizedDataset.getDataset());
try{
testInstance(ag_entry);
}
catch(NullPointerException e){
return 1;
}
String class_interval = ag_entry.stringValue(ag_entry.classIndex());
//System.out.println("\nAgent: "+ ag_entry);
/* Parse class interval*/
class_interval = class_interval.substring(2, class_interval.length()-2);
class_bounds = class_interval.split("-");
min = parseMin();
max = parseMax();
//System.out.println("Min "+min+" Max "+max);
//return min + (max-min)/2;
return max;
}
}
private double parseMax() {
//System.out.println(" substring: "+classBounds[i])
int i=0;
int j = 0;
double res = 0;
while(i<class_bounds.length){
String string = class_bounds[i];
String substring = null;
do{
try{
substring = string.substring(j);
if(substring.equals("inf")){
res = 1;
class_bounds[i] = "";
return res;
}
res = Double.parseDouble(substring);
class_bounds[i] = "";
return res;
}catch(Exception e){
j++;
}
}while(substring.length() != 0);
j=0;
i++;
}
/*
* if no maximum is found then return the same value of min
*/
return min;
}
private double parseMin() {
//System.out.println(" substring: "+classBounds[i])
int i=0;
int j = 0;
double res = 0;
while(i<class_bounds.length){
String string = class_bounds[i];
String substring = null;
do{
try{
substring = string.substring(j);
//System.out.println("Min: "+substring+" lenght: "+substring.length()+" i: "+i+" j: "+j);
if(substring.equals("inf")){
res = 0;
//System.out.println("Min "+substring);
class_bounds[i] = "";
return res;
}
res = Double.parseDouble(substring);
class_bounds[i] = "";
return res;
}catch(Exception e){
j++;
}
System.out.println(substring);
}while(substring.length() != 0);
j=0;
i++;
}
System.err.println("Error: Min not correctly parsed");
return res;
}
@SuppressWarnings("unused")
public static void main(String[] args){
try{
final long startTime = System.currentTimeMillis();
final long endTime;
final float duration;
// load data
ArffLoader loader = new ArffLoader();
loader.setFile(new File("./src/trust/weka4jason/trainingSet.arff"));
Instances data = loader.getDataSet();
WekaBinClassifier classifier = new WekaBinClassifier();
classifier.setWekaOptions("-F -B 10 -M -1.0 -R last");
//classifier.setDataset(data);
classifier.addInstanceToDataset(1, "appendicitis", "ent", "careful", "female", 0.375);
classifier.addInstanceToDataset(2, "otitis", "pediatrician", "careful", "male", 0.393939);
classifier.addInstanceToDataset(3, "chickenpox", "pediatrician", "distracted", "female", 0.77777);
classifier.getClassifier();
//System.out.println(classifier.);
/*
endTime = System.currentTimeMillis();;
duration = (endTime - startTime)/1000F;
System.out.println("\nElapsed time: "+(duration)+"sec");
//test on instance
Instance instance = new DenseInstance(5);
instance.setValue(data.attribute("Task"), "chickenpox");
instance.setValue(data.attribute("Ability"), "pediatrician");
instance.setValue(data.attribute("Dispos ition"), "distracted");
instance.setValue(data.attribute("Cross"), "female");
classifier.testInstance(instance);
System.out.println(instance);
*/
System.out.println("\nTrust for instance chickenpox, pediatrician, distracted, female...");
System.out.println("Trust "+classifier.agentTrustEvuation("chickenpox", "pediatrician", "distracted", "female"));
System.out.println("\nTrust for instance appendicitis,ent,careful,female...");
System.out.println("Trust "+ classifier.agentTrustEvuation("appendicitis","ent","careful","female"));
}catch(Exception e){
e.printStackTrace();
}
}
}