|
ppforest2 v0.1.0
Projection Pursuit Decision Trees and Random Forests
|
ppforest2 uses the Visitor pattern (double dispatch) to traverse trees and models without dynamic_cast. You can add new traversal logic — statistics, export formats, analysis — by implementing a visitor, without modifying the model types.
Two visitor interfaces are available:
| Interface | Dispatches over | Use when |
|---|---|---|
| TreeNode::Visitor | TreeCondition (split), TreeResponse (leaf) | You need to walk the tree structure |
| Model::Visitor | Tree, Forest | You need to handle trees and forests differently |
Each visitable class has an accept() method that calls the appropriate visit() overload on the visitor:
This resolves both the node type and the visitor type at runtime without any casts.
TreeCondition (internal split node) provides:
projector — the projection vector (p) used at this splitthreshold — the split threshold in projected spacelower / upper — child nodes (TreeNode::Ptr)groups — set of group labels reachable from this nodepp_index_value — the PP index value achieved at this splittraining_spec — the TrainingSpec used to build this subtreeTreeResponse (leaf node) provides:
value — the predicted group labelTo walk the full tree, recursively call accept() on child nodes inside your visit(TreeCondition&) method:
Usage:
Usage:
Model::Visitor dispatches over Tree and Forest, useful when you need to handle them differently (e.g. serialisation, summary statistics).
Usage:
| Visitor | File | Purpose |
|---|---|---|
| VIVisitor | models/VIVisitor.hpp | Accumulates projection-based variable importance at each split |
| JsonNodeVisitor | serialization/Json.hpp | Serialises tree nodes to JSON |
| JsonModelVisitor | serialization/Json.hpp | Serialises Tree/Forest to JSON |
| NodeDataVisitor | models/Visualization.hpp | Routes observations through the tree, collects per-node histograms |
| BoundaryVisitor | models/Visualization.hpp | Projects decision boundaries into 2D for plotting |
| RegionVisitor | models/Visualization.hpp | Computes convex decision region polygons via Sutherland-Hodgman clipping |
int count, json result, std::vector<NodeData> nodes). Read them after accept() returns.cond.lower->accept(*this) and cond.upper->accept(*this) inside visit(TreeCondition&) to walk the full tree. Omit these calls if you only need to inspect the root.