package jadetree;

import java.util.HashMap;
import jutils.collections.CollectionUtils;
import jutlis.algebra.Function;
import jutlis.tuples.Holder;
import jutlis.tuples.HolderBase;
import jutlis.tuples.Tuple2;

/**
 *
 * @author kommusoft
 */
public class DecisionTreeUtils {

    public static <TSource, TTarget> double calculateEntropy(Iterable<? extends TSource> sources, final HashMap<TTarget, Integer> frequency, Function<TSource, TTarget> function, Holder<Integer> total) {
        int ttl = 0;
        for (TSource s : sources) {
            TTarget target = function.evaluate(s);
            CollectionUtils.incrementKey(frequency, target);
            ttl++;
        }
        double entropy = 0.0;
        for (Integer fi : frequency.values()) {
            entropy -= fi * Math.log(fi);
        }
        entropy = (entropy / ttl + Math.log(ttl)) / Math.log(2.0d);
        if (total != null) {
            total.setData(ttl);
        }
        return entropy;
    }

    /*public static <TSource, TTarget> int calculateEntropyFlipIndex(Iterable<? extends TSource> sources, final HashMap<TTarget, Integer> frequency, Function<TSource, TTarget> function, Tuple2<Integer, Double> total_entropy) {
     final double log2 = 1.0 / Math.log(2.0);
     int ttl = 0;
     for (TSource s : sources) {
     TTarget target = function.evaluate(s);
     CollectionUtils.incrementKey(frequency, target);
     ttl++;
     }
     double entropy = 0.0;
     for (Integer fi : frequency.values()) {
     double p = (double) fi / ttl;
     entropy -= p * log2 * Math.log(p);
     }
     if (total != null) {
     total.setData(ttl);
     }
     return entropy;
     }*/
    public static <TSource, TTarget> double calculateEntropyPartition(Iterable<? extends Iterable<? extends TSource>> sources, Function<TSource, TTarget> function) {
        final HashMap<TTarget, Integer> frequency = new HashMap<>();
        Holder<Integer> ttl = new HolderBase<>();
        int total = 0;
        int subtotal;
        double entropy = 0.0d;
        double subentropy;
        for (Iterable<? extends TSource> subsource : sources) {
            subentropy = calculateEntropy(subsource, frequency, function, ttl);
            frequency.clear();
            subtotal = ttl.getData();
            entropy += subentropy * subtotal;
            total += subtotal;
        }
        return entropy / total;
    }

}

@@ -316,32 +316,35 @@
 double calculate
+Raw
 Entropy(Iterable
@@ -473,24 +473,24 @@
 r%3E total) %7B%0A
-
         int 
@@ -809,76 +809,8 @@
   %7D%0A
-        entropy = (entropy / ttl + Math.log(ttl)) / Math.log(2.0d);%0A
     
@@ -911,18 +911,16 @@
  %7D%0A%0A    
-/*
 public s
@@ -944,19 +944,22 @@
 Target%3E 
-int
+double
  calcula
@@ -971,17 +971,8 @@
 ropy
-FlipIndex
 (Ite
@@ -1089,22 +1089,22 @@
 on, 
-Tuple2
+Holder
 %3CInteger
 , Do
@@ -1103,63 +1103,317 @@
 eger
-, Double%3E total_entropy) %7B%0A     final double log2 = 1.0
+%3E total) %7B%0A        Holder%3CInteger%3E subholder = total;%0A        if (subholder == null) %7B%0A            subholder = new HolderBase%3C%3E();%0A        %7D%0A        double entropy = calculateRawEntropy(sources, frequency, function, total);%0A        int ttl = subholder.getData();%0A        return (entropy / ttl + Math.log(ttl))
  / M
@@ -1427,29 +1427,367 @@
 (2.0
+d
 );%0A    
- int ttl = 0;%0A
+%7D%0A%0A    public static %3CTSource, TTarget%3E int calculateEntropyFlipIndex(Iterable%3C? extends TSource%3E sources, Function%3CTSource, TTarget%3E function, Tuple2%3CInteger, Double%3E total_entropy) %7B%0A        final HashMap%3CTTarget, Integer%3E frequency = new HashMap%3C%3E();%0A        int ttl = 0x00, maxFlip = -0x01;%0A        double maxEntropy = 0.0d, rawEntropy = 0.0d;%0A   
     
@@ -1811,24 +1811,31 @@
  sources) %7B%0A
+       
      TTarget
@@ -1862,24 +1862,31 @@
 valuate(s);%0A
+       
      Collect
@@ -1923,24 +1923,31 @@
 y, target);%0A
+       
      ttl++;%0A
@@ -1955,222 +1955,193 @@
     
-%7D%0A
      
-double entropy = 0.0;%0A     for (Integer fi : frequency.values()) %7B%0A     double p = (double) fi / ttl;%0A
+  //TODO: recalculate entropy%0A            if (rawEntropy %3E maxEntropy) %7B%0A           
      
-e
+maxE
 ntropy 
--
 = 
-p * log2 * Math.log(p)
+rawEntropy
 ;%0A     
-%7D%0A
      
-if (total != null) %7B%0A     total.setData(ttl);%0A
+      maxFlip = ttl - 0x01;%0A            %7D%0A%0A  
      
+ 
 %7D%0A
+   
     
@@ -2152,25 +2152,23 @@
 urn 
-entropy
+maxFlip
 ;%0A
- 
     %7D
-*/
+%0A
 %0A   

introduce concept of raw entropy