37typedef tree<Node>::pre_order_iterator
Iter;
38typedef tree<Node>::post_order_iterator
PostIter;
75 std::optional<std::reference_wrapper<SearchSpace>>
SSref;
78 Program(
const std::reference_wrapper<SearchSpace> s,
const tree<Node> t)
81 SSref = std::optional<std::reference_wrapper<SearchSpace>>{s};
88 SSref = std::optional<std::reference_wrapper<SearchSpace>>{s};
94 auto head =
Tree.begin();
96 return head.node->get_complexity();
102 auto head =
Tree.begin();
104 return head.node->get_linear_complexity();
110 int size(
bool include_weight=
true)
const{
111 auto head =
Tree.begin();
113 return head.node->get_size(include_weight);
123 return top.node->get_size(include_weight);
131 return 1+
Tree.max_depth();
139 return 1+
Tree.max_depth(top);
147 return 1+
Tree.depth(top);
153 this->is_fitted_ =
true;
159 template <
typename R,
typename W>
165 return Tree.begin().node->predict<R>(d, weights);
170 float const * wptr = weights.data();
182 template <
typename R = RetType>
195 template <
typename R = RetType>
208 template <
typename R = RetType>
220 template <PT P = PType>
253 template <PT P = PType>
275 const auto& node = i.node->data;
280 || (node.get_is_weighted() &&
IsWeighable(node.ret_type)) )
297 const auto& node = t.node->data;
299 || (node.get_is_weighted() &&
IsWeighable(node.ret_type)) )
323 auto& node = i.node->data;
325 || (node.get_is_weighted() &&
IsWeighable(node.node_type)) )
342 void lock_nodes(
int end_depth=0,
bool keep_leaves_unlocked=
true)
351 auto tree_iter =
Tree.begin();
353 std::for_each(
Tree.begin(),
Tree.end(),
355 auto d = Tree.depth(tree_iter);
356 std::advance(tree_iter, 1);
358 if (keep_leaves_unlocked && IsLeaf(n.node_type))
363 if (n.node_type==NodeType::SplitBest)
365 if (keep_leaves_unlocked)
367 n.set_keep_split_feature(false);
372 n.set_keep_split_feature(d+1<=end_depth);
395 string get_model(
string fmt=
"compact",
bool pretty=
false)
const
397 auto head =
Tree.begin();
399 return head.node->get_tree_model(pretty);
402 return head.node->get_model(pretty);
415 string out =
"digraph G {\n";
416 if (! extras.empty())
417 out += fmt::format(
"{}\n", extras);
419 auto get_id = [](
const auto& n){
421 return n->data.get_name(
false);
423 return fmt::format(
"{}",fmt::ptr(n)).substr(2);
426 std::map<string, unsigned int> node_count;
428 for (
Iter iter =
Tree.begin(); iter!=
Tree.end(); iter++)
430 const auto& parent = iter.node;
433 string parent_id = get_id(parent);
443 if (i==0 && parent->data.get_is_weighted())
445 out +=
"y [shape=box];\n";
446 out += fmt::format(
"y -> \"{}\" [label=\"{:.2f}\"];\n",
455 string node_label = parent->data.get_name(is_constant);
458 node_label = fmt::format(
"{}>={:.2f}?", parent->data.get_feature(), parent->data.W);
461 node_label = fmt::format(
"Add");
464 string node_style = parent->data.get_prob_change() >0.0 ?
"" :
", style=filled, fillcolor=lightcoral";
465 out += fmt::format(
"\"{}\" [label=\"{}\"{}];\n", parent_id, node_label, node_style);
468 auto kid = iter.node->first_child;
469 for (
int j = 0; j < iter.number_of_children(); ++j)
471 string edge_label=
"";
472 string head_label=
"";
473 string tail_label=
"";
474 bool use_head_tail_labels =
false;
476 string kid_id = get_id(kid);
480 if (kid->data.get_is_weighted()
484 edge_label = fmt::format(
"{:.2f}",kid->data.W);
488 use_head_tail_labels=
true;
490 tail_label = fmt::format(
">={:.2f}",parent->data.W);
496 head_label=edge_label;
499 use_head_tail_labels=
true;
506 head_label = edge_label;
509 if (use_head_tail_labels){
510 out += fmt::format(
"\"{}\" -> \"{}\" [headlabel=\"{}\",taillabel=\"{}\"];\n",
518 out += fmt::format(
"\"{}\" -> \"{}\" [label=\"{}\"];\n",
524 kid = kid->next_sibling;
530 out += fmt::format(
"\"{}\" -> \"{}\" [label=\"\"];\n",
536 out += fmt::format(
"\"{}\" [label=\"{:.2f}\"{}];\n",
552 vector<Node> linear_program;
554 linear_program.push_back(i.node->data);
555 return linear_program;
566template<ProgramType PType>
573 WO.update((*
this), d);
580template<ProgramType PType>
586template<ProgramType PType>
589 j.at(
"Tree").get_to(p.
Tree);
holds variable type data.
#define HANDLE_ERROR_THROW(err)
< nsga2 selection operator for getting the front
auto Isnt(DataType dt) -> bool
Eigen::Array< bool, Eigen::Dynamic, 1 > ArrayXb
auto IsWeighable() noexcept -> bool
void from_json(const json &j, Fitness &f)
auto Is(NodeType nt) -> bool
tree< Node >::pre_order_iterator Iter
tree< Node >::post_order_iterator PostIter
void to_json(json &j, const Fitness &f)
Eigen::Array< int, Eigen::Dynamic, 1 > ArrayXi
An individual program, a.k.a. model.
Program(const std::reference_wrapper< SearchSpace > s, const tree< Node > t)
TreeType predict_proba(const Dataset &d)
void lock_nodes(int end_depth=0, bool keep_leaves_unlocked=true)
Iterates over the program, locking the nodes until it reaches a certain depth. If the node is a Split...
void update_weights(const Dataset &d)
Updates the program's weights using non-linear least squares.
typename std::conditional_t< PType==PT::Regressor, ArrayXf, std::conditional_t< PType==PT::BinaryClassifier, ArrayXb, std::conditional_t< PType==PT::MulticlassClassifier, ArrayXi, std::conditional_t< PType==PT::Representer, ArrayXXf, ArrayXf > > > > RetType
the return type of the tree when calling :func:predict.
std::optional< std::reference_wrapper< SearchSpace > > SSref
int linear_complexity() const
count the linear complexity of the program.
RetType predict(const Ref< const ArrayXXf > &X)
Convenience function to call predict directly from X data.
void set_weights(const ArrayXf &weights)
Set the weights in the tree from an array of weights.
TreeType predict(const Dataset &d)
the standard predict function. Returns the output of the Tree directly.
static constexpr PT program_type
R predict_with_weights(const Dataset &d, const W **weights)
std::conditional_t< PType==PT::BinaryClassifier, ArrayXf, std::conditional_t< PType==PT::MulticlassClassifier, ArrayXXf, RetType > > TreeType
the type of output from the tree object
int complexity() const
count the (recursive) complexity of the program.
int size_at(Iter &top, bool include_weight=true) const
count the size of a given subtree, optionally including the weights in weighted nodes....
ArrayXf get_weights()
Get the weights of the tree as an array.
Program< PType > & fit(const Dataset &d)
int depth() const
count the tree depth of the program. The depth is not influenced by weighted nodes.
auto predict_with_weights(const Dataset &d, const ArrayXf &weights)
int get_n_weights() const
returns the number of weights in the program.
int depth_at(Iter &top) const
count the depth of a given subtree. The depth is not influenced by weighted nodes....
vector< Node > linearize() const
turns program tree into a linear program.
ArrayXi predict(const Dataset &d)
Specialized predict function for multiclass classification.
void set_search_space(const std::reference_wrapper< SearchSpace > s)
ArrayXb predict(const Dataset &d)
Specialized predict function for binary classification.
string get_dot_model(string extras="") const
string get_model(string fmt="compact", bool pretty=false) const
Get the model as a string.
TreeType predict_proba(const Ref< const ArrayXXf > &X)
Predict probabilities from X.
int depth_to_reach(Iter &top) const
count the depth until reaching the given subtree. The depth is not influenced by weighted nodes....
Program< PType > & fit(const Ref< const ArrayXXf > &X, const Ref< const ArrayXf > &y)
Convenience function to call fit directly from X,y data.
int size(bool include_weight=true) const
count the tree size of the program, including the weights in weighted nodes.
Holds a search space, consisting of operations and terminals and functions, and methods to sample tha...