package jclassifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.TreeMap;
import jclassifier.Quantizer.AdaptiveQuantizer;
import net.sourceforge.aprog.tools.MathTools.Statistics;
/**
* @author codistmonk (creation 2013-07-02)
*/
public final class HierarchicalAdaptiveQuantizer extends AdaptiveQuantizer {
public HierarchicalAdaptiveQuantizer() {
this(256);
}
public HierarchicalAdaptiveQuantizer(final int quanta) {
super(quanta);
}
@Override
protected final Double[] remapData(final TreeMap<Double, Double> data) {
// protected final double[] remapData(final DictionaryDoubleDouble data) {
final int n = data.size();
// final int n = data.getKeys().length;
final int excess = n - this.getQuantification();
if (excess <= 0) {
return data.keySet().toArray(new Double[n]);
// return data.getKeys();
}
final List<Node> nodes = new ArrayList<Node>(n);
for (final Map.Entry<Double, Double> entry : data.entrySet()) {
nodes.add(new Leaf(nodes.size(), entry.getKey(), entry.getValue()));
}
// for (int i = 0; i < n; ++i) {
// nodes.add(new Leaf(nodes.size(), data.getKeys()[i], data.getValues()[i]));
// }
final PriorityQueue<InterNode> queue = new PriorityQueue<InterNode>();
for (int i = 0; i < n - 1; ++i) {
queue.add(new InterNode(nodes.get(i), nodes.get(i + 1)));
}
for (int i = 0; i < excess; ++i) {
InterNode node = queue.poll();
while (node.getLeft().isLocked() || node.getRight().isLocked()) {
node = queue.poll();
}
node.getLeft().setLocked(true);
node.getRight().setLocked(true);
nodes.set(node.getLeftIndex(), node);
nodes.set(node.getRightIndex(), node);
if (0 < node.getLeftIndex()) {
queue.add(new InterNode(nodes.get(node.getLeftIndex() - 1), node));
}
if (node.getRightIndex() + 1 < n) {
queue.add(new InterNode(node, nodes.get(node.getRightIndex() + 1)));
}
}
{
final Double[] result = new Double[this.getQuantification()];
// final double[] result = new double[this.getQuantification()];
int nodeIndex = 0;
int keyIndex = 0;
while (nodeIndex < n) {
final Node node = nodes.get(nodeIndex);
result[keyIndex++] = node.getStatistics().getMean();
nodeIndex = node.getRightIndex() + 1;
}
return result;
}
}
/**
* @author codistmonk (creation 2013-07-02)
*/
public static abstract class Node implements Comparable<Node> {
private final int leftIndex;
private final int rightIndex;
private boolean locked;
private final Statistics statistics;
public Node(final int leftIndex, final int rightIndex) {
this.leftIndex = leftIndex;
this.rightIndex = rightIndex;
this.statistics = new Statistics();
}
public final int getLeftIndex() {
return this.leftIndex;
}
public final int getRightIndex() {
return this.rightIndex;
}
public final boolean isLocked() {
return this.locked;
}
public final void setLocked(final boolean locked) {
this.locked = locked;
}
public final Statistics getStatistics() {
return this.statistics;
}
public final double getScore() {
// return this.getStatistics().getCount() / square(this.getStatistics().getAmplitude());
return this.getStatistics().getVariance();
}
@Override
public final int compareTo(final Node that) {
return Double.compare(this.getScore(), that.getScore());
// return Double.compare(that.getScore(), this.getScore());
}
@Override
public final String toString() {
return "[" + this.getLeftIndex() + ".." + this.getRightIndex() + "]";
}
}
/**
* @author codistmonk (creation 2013-07-02)
*/
public static final class InterNode extends Node {
private final Node left;
private final Node right;
public InterNode(final Node left, final Node right) {
super(left.getLeftIndex(), right.getRightIndex());
this.left = left;
this.right = right;
this.getStatistics().addAll(left.getStatistics());
this.getStatistics().addAll(right.getStatistics());
}
public final Node getLeft() {
return this.left;
}
public final Node getRight() {
return this.right;
}
}
/**
* @author codistmonk (creation 2013-07-02)
*/
public static final class Leaf extends Node {
public Leaf(final int index, final double value, final double count) {
super(index, index);
this.getStatistics().addValue(value, count);
}
}
}