*/
public class ID3AttributeSelector implements AttributeSelector<Boolean> {
@Override
public Attribute select(final Set<Example<Boolean>> examples, final Set<Attribute> availableAttributes, final Set<Attribute> usedAttributes) {
Attribute attribute = null;
float attributeRem = Float.MAX_VALUE;
int attributeValueCount = Integer.MAX_VALUE;
float positives = 0;
float negatives = 0;
final Map<Attribute, Map<AttributeValue, Pair>> attributeUsage = new HashMap<Attribute, Map<AttributeValue, Pair>>();
/* Make array for performance */
final Example<Boolean>[] exampleArray = examples.toArray(new Example[0]);
final int examplesSize = exampleArray.length;
for (final Attribute attr : availableAttributes) {
if (usedAttributes.contains(attr)) {
continue;
}
final Map<AttributeValue, Pair> valueUsage = new HashMap<AttributeValue, Pair>();
attributeUsage.put(attr, valueUsage);
for (int i = 0; i < examplesSize; i++) {
final AttributeValue value = exampleArray[i].getValues().get(attr);
Pair valueUsageExamples = valueUsage.get(value);
if (valueUsageExamples == null) {
valueUsageExamples = new Pair();
valueUsage.put(value, valueUsageExamples);
}
if (exampleArray[i].getResult()) {
++valueUsageExamples.positive;
++positives;
} else {
++valueUsageExamples.negative;
++negatives;
}
}
}
if (positives > 0 && negatives > 0) {
for (final Map.Entry<Attribute, Map<AttributeValue, Pair>> entry : attributeUsage.entrySet()) {
final Attribute attr = entry.getKey();
final float rem = Pair.rem(entry.getValue().values(), positives, negatives);
if (rem < attributeRem) {
attribute = attr;
attributeRem = rem;