package quickml.supervised.tree.nodes; import com.google.common.base.Predicate; import quickml.data.AttributesMap; import quickml.data.instances.Instance; import quickml.supervised.tree.summaryStatistics.ValueCounter; import java.io.Serializable; import java.util.Map; //signature ensures that Branch<VC, N> extends N (as it extends Node<VC, N>, which has exactly one valid extension: N). public abstract class Branch<VC extends ValueCounter<VC>> implements Node<VC>, Serializable { private static final long serialVersionUID = 8290012786245422175L; public final String attribute; private Node<VC> trueChild, falseChild; public VC valueCounter; protected Node<VC> parent; protected final double probabilityOfTrueChild; public final double score; protected final int depth; public Branch(Branch<VC> parent, final String attribute, double probabilityOfTrueChild, double score, VC valueCounter) { this.parent = parent; this.attribute = attribute; this.depth = (parent!=null) ? parent.depth + 1 : 0; this.score = score; this.valueCounter = valueCounter; this.probabilityOfTrueChild = probabilityOfTrueChild; } public void setTrueChild(Node<VC> trueChild) { this.trueChild = trueChild; } public void setFalseChild(Node<VC> falseChild) { this.falseChild = falseChild; } public Node<VC> getTrueChild(){ return trueChild; } public Node<VC> getFalseChild(){ return falseChild; } public int getDepth() { return depth; } public VC getValueCounter() { return valueCounter; } public double getProbabilityOfTrueChild() { return probabilityOfTrueChild; } public double getScore() { return score; } public Node<VC> getParent() { return parent; } public boolean isEmpty() { return attribute.isEmpty(); } public abstract boolean decide(Map<String, Serializable> attributes); @Override public Leaf<VC> getLeaf(final AttributesMap attributes) { if (decide(attributes)) return trueChild.getLeaf(attributes); else return falseChild.getLeaf(attributes); } @Override public int getSize() { return 1 + trueChild.getSize() + falseChild.getSize(); } public Predicate<Instance<AttributesMap, Serializable>> getInPredicate() { return new Predicate<Instance<AttributesMap, Serializable>>() { @Override public boolean apply(final Instance<AttributesMap, Serializable> input) { return decide(input.getAttributes()); } }; } @Override public void calcLeafDepthStats(final LeafDepthStats stats) { trueChild.calcLeafDepthStats(stats); falseChild.calcLeafDepthStats(stats); } @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final Branch<VC> branch = (Branch<VC>) o; if (!attribute.equals(branch.attribute)) return false; if (!falseChild.equals(branch.falseChild)) return false; if (!trueChild.equals(branch.trueChild)) return false; return true; } //TODO: this is wildly inefficient @Override public int hashCode() { int result = attribute.hashCode(); result = 31 * result + trueChild.hashCode(); result = 31 * result + falseChild.hashCode(); return result; } }