Partly implement determine_split_candidates()
Fix: initialize class attributes

Previously we just did:
>> some_attribute_ = attribute
Now we do:
>> self.some_attribute = attribute
Partly implement determine_candidate_numeric_splits()
Fully implement determine_candidate_splits()
Write method to determine priority of classes
Simplify setting class priority, assume binary class
Write function to calculate entropy
Add asserts, comments to DT_learner constructor
Write function for instance for traverse one tree node
Write function to calculate conditional entropy
Write function to compute info gain knowing a split
Move partition_instances() to its own function

Previously it was nested in get_conditional_entropy().
We move it because it's a useful atomic function that can be called at other
places, independent of get_conditional_entropy()
Fix: determine_split_candidates() returns value

Previously we forgot to get the function to return what it's supposed to.
Fix: remove extra open bracket in Node.add_child()
Write method to print node recursively
Implement make_subtree() in DT_learner
Assume class label passed to learner is norminal
Write wrapper method fit() to fit DT
Write method predict() to predict class of an instance
Write method to print decision tree