package org.streaminer.stream.classifier.tree;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Represents a node in a {@link HoeffdingTreeModel}
* @author Tobias Beckers
*
*/
public class HoeffdingTreeNode implements Serializable {
private static final long serialVersionUID = 1L;
/** the feature associated with this node (split feature) */
private String feature;
/** contains a child for each possible branch (/value) for this node (/feature) */
private final Map<Serializable, HoeffdingTreeNode> children;
/** only set for leafs: The predicted class for all examples sorted to this node */
private Serializable label;
/**
* Initializes a new {@link HoeffdingTreeNode} with no feature and no children but a label.
* @param label the initial label for the new node
*/
public HoeffdingTreeNode(Serializable label) {
this.feature = null;
this.label = label;
this.children = new HashMap<Serializable, HoeffdingTreeNode>();
}
/**
* Sets the label for this node. Overwrites the previous label if there was one.
* @param label the (new) label
*/
public void setLabel(Serializable label) {
this.label = label;
}
/**
* Returns the label of this node.
* @return the label
*/
public Serializable getLabel() {
return this.label;
}
/**
* Declares this node to be a split on the specified feature.
* @param feature the split feature
*/
public void setFeature(String feature) {
this.feature = feature;
}
/**
* Returns the feature on which this node tests.
* @return the split feature
*/
public String getFeature() {
return this.feature;
}
/**
* Returns true iff this node actually represents a leaf in the contained tree.
* @return true iff this node is a leaf
*/
public boolean isLeaf() {
return (this.children == null || this.children.isEmpty());
}
/**
* Adds a child to this node (which is then the parent of the specified node) for the specified branch.
* @param child a node which should be a child of this node
* @param value a value for the feature of this node to specify the branch
*/
public void addChild(HoeffdingTreeNode child, Serializable value) {
this.children.put(value, child);
}
/**
* Returns the node following the branch induced by the specified value.
* @param value a valid value for the feature represented by this node
* @return the next node following the path of the given value
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public HoeffdingTreeNode getchild(Serializable value, Class<?> featureType) {
if( featureType == Double.class )
return this.children.get(HoeffdingTree.numericToNominal((Set)(this.children.keySet()), (Comparable)value));
return children.get( value );
}
/**
* Returns a string representation of the subtree beginning at this node.
* @return a string representation of the subtree beginning at this node
*/
@Override
public String toString() {
return this.toString(0);
}
/**
* Returns a string representation of the subtree beginning at this node. Adds the specified number of blanks to each line.
* @param spaceNumber the number of blanks for each line
* @return a string representation of the subtree beginning at this node
*/
protected String toString(int spaceNumber) {
StringBuffer out = new StringBuffer();
out.append("["+this.feature+"|"+this.label+"]");
for (Serializable value : this.children.keySet()) {
out.append("\n");
int labelLength = 0;
if (this.label == null) { labelLength = 4;}
else { labelLength = this.label.toString().length(); }
int spaceLength = spaceNumber+this.feature.length()+labelLength+3;
for (int i = 0; i < spaceLength; i++) {
out.append(" ");
}
out.append("-- "+value.toString()+" --");
out.append(this.children.get(value).toString(spaceLength+value.toString().length()+6));
}
return out.toString();
}
}