{"id":487,"date":"2024-06-09T14:45:00","date_gmt":"2024-06-09T13:45:00","guid":{"rendered":"https:\/\/noiseonthenet.space\/noise\/?p=487"},"modified":"2024-06-09T15:09:11","modified_gmt":"2024-06-09T14:09:11","slug":"growing-a-decision-tree","status":"publish","type":"post","link":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/","title":{"rendered":"Growing a (Decision) Tree"},"content":{"rendered":"<div id=\"table-of-contents\" role=\"doc-toc\">\n<h2>Table of Contents<\/h2>\n<div id=\"text-table-of-contents\" role=\"doc-toc\">\n<ul>\n<li><a href=\"#orge00b602\">Basic data structure<\/a><\/li>\n<li><a href=\"#org7097c29\">Predicting class at a given node<\/a><\/li>\n<li><a href=\"#org7a140ce\">Evaluating the best split point<\/a><\/li>\n<li><a href=\"#orgc6225d7\">Stopping rules<\/a><\/li>\n<li><a href=\"#org1747ee4\">Builder pattern in Rust<\/a><\/li>\n<li><a href=\"#org9a70d86\">Iterative node building<\/a><\/li>\n<li><a href=\"#orgc3a2c12\">Dumping the tree<\/a>\n<ul>\n<li><a href=\"#org6b75931\">Pre-order depth first traversal<\/a><\/li>\n<li><a href=\"#orgb72ba6a\">creating a Dot DSL reification<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#org777acb0\">Some effects of tree creation options<\/a>\n<ul>\n<li><a href=\"#orgd275090\">Not reusing features<\/a><\/li>\n<li><a href=\"#org535e008\">Limiting tree depth<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#orgffeb136\">Conclusions?<\/a><\/li>\n<\/ul>\n<\/div>\n<\/div>\n<div id=\"orgfa08c60\" class=\"figure\"> <p><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_full_tree_result.png?ssl=1\" alt=\"post017_full_tree_result.png\" \/> <\/p> <\/div>\n\n<p> In this post I will complete the creation of the decision tree by iteratively building it with Gini metric; I will show a pre-order depth first traversal which will be used to create tree charts using graphviz dot language <\/p>\n\n<p> The code for this post is available <a href=\"https:\/\/github.com\/noiseOnTheNet\/post017_binary_decision_tree\">here<\/a> <\/p>\n\n<p> In the last post we saw how to evaluate a Gini inpurity index across all features <a href=\"https:\/\/noiseonthenet.space\/noise\/2024\/05\/sowing-a-decision-tree\/\">Sowing a (Decision) Tree<\/a> <\/p>\n<div id=\"outline-container-orge00b602\" class=\"outline-2\">\n<h2 id=\"orge00b602\">Basic data structure<\/h2>\n<div class=\"outline-text-2\" id=\"text-orge00b602\">\n<p> Here I will describe what will be the content of each node in the decision tree. <\/p>\n\n<p> the main tree node contains the classification of the current dataset according to the majority; in case of even count of two or more classes the result is random. <\/p>\n\n<p> With the predicted class a confidence is calculated which is the frequency of the class in the current dataset <\/p>\n\n<p> Optionally a further split may be added which contains the chosen feature and a floating point number representing the threshold separating the left sub-branch from the right, here we can save the metric used to evaluate the split. <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\">\n<span style=\"color: #51afef; font-weight: bold;\">#<\/span><span style=\"color: #51afef; font-weight: bold;\">[<\/span><span style=\"color: #51afef; font-weight: bold;\">derive<\/span><span style=\"color: #c678dd; font-weight: bold;\">(<\/span><span style=\"color: #51afef; font-weight: bold;\">Debug<\/span><span style=\"color: #c678dd; font-weight: bold;\">)<\/span><span style=\"color: #51afef; font-weight: bold;\">]<\/span>\n<span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">struct<\/span> <span style=\"color: #ECBE7B;\">Rule<\/span> <span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #dcaeea;\">dimension<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n    <span style=\"color: #dcaeea;\">cutoff<\/span>: <span style=\"color: #ECBE7B;\">f64<\/span>,\n    <span style=\"color: #dcaeea;\">metric<\/span>: <span style=\"color: #ECBE7B;\">f64<\/span>,\n<span style=\"color: #51afef;\">}<\/span>\n\n<span style=\"color: #51afef; font-weight: bold;\">#<\/span><span style=\"color: #51afef; font-weight: bold;\">[<\/span><span style=\"color: #51afef; font-weight: bold;\">derive<\/span><span style=\"color: #c678dd; font-weight: bold;\">(<\/span><span style=\"color: #51afef; font-weight: bold;\">Debug<\/span><span style=\"color: #c678dd; font-weight: bold;\">)<\/span><span style=\"color: #51afef; font-weight: bold;\">]<\/span>\n<span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">struct<\/span> <span style=\"color: #ECBE7B;\">Decision<\/span> <span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #dcaeea;\">rule<\/span>: <span style=\"color: #ECBE7B;\">Option<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">Rule<\/span><span style=\"color: #c678dd;\">&gt;<\/span>,\n    <span style=\"color: #dcaeea;\">confidence<\/span>: <span style=\"color: #ECBE7B;\">f64<\/span>,\n    <span style=\"color: #dcaeea;\">prediction<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n<span style=\"color: #51afef;\">}<\/span>\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"outline-container-org7097c29\" class=\"outline-2\">\n<h2 id=\"org7097c29\">Predicting class at a given node<\/h2>\n<div class=\"outline-text-2\" id=\"text-org7097c29\">\n<p> Here I will describe how each tree node will predict a class from the training dataset <\/p>\n\n<p> In the training stage, at each node we have an associated subset of the original training set. <\/p>\n\n<p> The predicted category will be the most populated; we can associate a confidence with this prediction by estimating the probability of finding a sample in the predicted class <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\"><span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">predict_majority_dataframe<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #51afef;\">&gt;(<\/span>\n    <span style=\"color: #dcaeea;\">data<\/span>: &amp; '<span style=\"color: #dcaeea;\">a<\/span> <span style=\"color: #ECBE7B;\">DataFrame<\/span>, <span style=\"color: #dcaeea;\">target<\/span>: &amp; <span style=\"color: #ECBE7B;\">str<\/span>\n<span style=\"color: #51afef;\">)<\/span> -&gt; <span style=\"color: #ECBE7B;\">PolarsResult<\/span><span style=\"color: #51afef;\">&lt;<\/span><span style=\"color: #ECBE7B;\">Decision<\/span><span style=\"color: #51afef;\">&gt;<\/span> <span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">extract the categorical target column<\/span>\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">labels<\/span> = data.column<span style=\"color: #c678dd;\">(<\/span>target<span style=\"color: #c678dd;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>.categorical<span style=\"color: #c678dd;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>;\n\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">total<\/span> = labels.len<span style=\"color: #c678dd;\">()<\/span> <span style=\"color: #51afef;\">as<\/span> <span style=\"color: #ECBE7B;\">f64<\/span>;\n\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">count all categories and sort them<\/span>\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">result_count<\/span> = labels.value_counts<span style=\"color: #c678dd;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>;\n\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">get the most frequent category<\/span>\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">result_cat<\/span> = result_count.head<span style=\"color: #c678dd;\">(<\/span><span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #98be65;\">(<\/span><span style=\"color: #da8548; font-weight: bold;\">1<\/span><span style=\"color: #98be65;\">)<\/span><span style=\"color: #c678dd;\">)<\/span>;\n\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">transform the series into a categorical vector<\/span>\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">actual_cat<\/span> = result_cat\n        .column<span style=\"color: #c678dd;\">(<\/span>target<span style=\"color: #c678dd;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>\n        .categorical<span style=\"color: #c678dd;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>;\n\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">collect all categories as strings<\/span>\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">string_cat<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">String<\/span><span style=\"color: #c678dd;\">&gt;<\/span> = actual_cat\n        .iter_str<span style=\"color: #c678dd;\">()<\/span>\n        .flatten<span style=\"color: #c678dd;\">()<\/span>\n        .map<span style=\"color: #c678dd;\">(<\/span>|name| <span style=\"color: #98be65;\">(<\/span>*name<span style=\"color: #98be65;\">)<\/span>.into<span style=\"color: #98be65;\">()<\/span><span style=\"color: #c678dd;\">)<\/span>\n        .collect<span style=\"color: #c678dd;\">()<\/span>;\n\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">probability<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">f64<\/span><span style=\"color: #c678dd;\">&gt;<\/span>= result_cat\n        .column<span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98be65;\">\"counts\"<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>\n        .<span style=\"color: #ECBE7B;\">u32<\/span><span style=\"color: #c678dd;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>\n    .iter<span style=\"color: #c678dd;\">()<\/span>\n    .flatten<span style=\"color: #c678dd;\">()<\/span>\n    .map<span style=\"color: #c678dd;\">(<\/span>|c| <span style=\"color: #98be65;\">(<\/span>c <span style=\"color: #51afef;\">as<\/span> <span style=\"color: #ECBE7B;\">f64<\/span><span style=\"color: #98be65;\">)<\/span>\/total<span style=\"color: #c678dd;\">)<\/span>\n        .collect<span style=\"color: #c678dd;\">()<\/span>;\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">return the most common category as a string<\/span>\n    <span style=\"color: #51afef;\">return<\/span> <span style=\"color: #ECBE7B;\">Ok<\/span><span style=\"color: #c678dd;\">(<\/span>\n        <span style=\"color: #ECBE7B;\">Decision<\/span><span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #dcaeea;\">rule<\/span>: <span style=\"color: #ECBE7B;\">None<\/span>,\n            <span style=\"color: #dcaeea;\">prediction<\/span>: string_cat\n                .get<span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #da8548; font-weight: bold;\">0<\/span><span style=\"color: #a9a1e1;\">)<\/span>\n                .unwrap<span style=\"color: #a9a1e1;\">()<\/span>\n                .to_string<span style=\"color: #a9a1e1;\">()<\/span>,\n            <span style=\"color: #dcaeea;\">confidence<\/span>: probability\n                .get<span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #da8548; font-weight: bold;\">0<\/span><span style=\"color: #a9a1e1;\">)<\/span>\n                .unwrap<span style=\"color: #a9a1e1;\">()<\/span>\n                .to_owned<span style=\"color: #a9a1e1;\">()<\/span>\n        <span style=\"color: #98be65;\">}<\/span>\n    <span style=\"color: #c678dd;\">)<\/span>;\n<span style=\"color: #51afef;\">}<\/span>\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"outline-container-org7a140ce\" class=\"outline-2\">\n<h2 id=\"org7a140ce\">Evaluating the best split point<\/h2>\n<div class=\"outline-text-2\" id=\"text-org7a140ce\">\n<p> The best feature and its split point is found by choosing the value that optimize the metric: <\/p>\n\n<ul class=\"org-ul\">\n<li>per each feature\n\n<ul class=\"org-ul\">\n<li>metric is evaluated in all split points<\/li>\n<\/ul><\/li>\n<li>all result are joined<\/li>\n<li>select the best pair of feature and split point according to the metric<\/li>\n<\/ul>\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\">\n<span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">evaluate_best_split<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #51afef;\">&gt;(<\/span>\n    <span style=\"color: #dcaeea;\">data<\/span>: &amp; <span style=\"color: #ECBE7B;\">DataFrame<\/span>,\n    <span style=\"color: #dcaeea;\">features<\/span>: &amp; <span style=\"color: #ECBE7B;\">HashSet<\/span> <span style=\"color: #c678dd;\">&lt;<\/span>&amp; <span style=\"color: #ECBE7B;\">str<\/span><span style=\"color: #c678dd;\">&gt;<\/span>,\n    <span style=\"color: #dcaeea;\">target<\/span>: &amp; <span style=\"color: #ECBE7B;\">str<\/span>,\n<span style=\"color: #51afef;\">)<\/span> -&gt; <span style=\"color: #ECBE7B;\">PolarsResult<\/span><span style=\"color: #51afef;\">&lt;<\/span><span style=\"color: #ECBE7B;\">Rule<\/span><span style=\"color: #51afef;\">&gt;<\/span> <span style=\"color: #51afef;\">{<\/span>\n\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">iteratively evaluate the metric on all features<\/span>\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">metrics<\/span>: <span style=\"color: #ECBE7B;\">PolarsResult<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #98be65;\">&lt;<\/span><span style=\"color: #ECBE7B;\">LazyFrame<\/span><span style=\"color: #98be65;\">&gt;<\/span><span style=\"color: #c678dd;\">&gt;<\/span> = features\n        .iter<span style=\"color: #c678dd;\">()<\/span>\n        .map<span style=\"color: #c678dd;\">(<\/span>|feature| <span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #ECBE7B;\">Ok<\/span><span style=\"color: #a9a1e1;\">(<\/span>evaluate_metric<span style=\"color: #51afef;\">(<\/span>&amp; data, feature, target<span style=\"color: #51afef;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>\n                .lazy<span style=\"color: #51afef;\">()<\/span>\n                .with_column<span style=\"color: #51afef;\">(<\/span>feature.lit<span style=\"color: #c678dd;\">()<\/span>.alias<span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98be65;\">\"feature\"<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #51afef;\">)<\/span><span style=\"color: #a9a1e1;\">)<\/span>\n        <span style=\"color: #98be65;\">}<\/span><span style=\"color: #c678dd;\">)<\/span>\n        .collect<span style=\"color: #c678dd;\">()<\/span>;\n\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">join all results in a single dataframe<\/span>\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">concat_rules<\/span> = <span style=\"color: #ECBE7B;\">UnionArgs<\/span> <span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #dcaeea;\">parallel<\/span>: <span style=\"color: #51afef;\">true<\/span>,\n        <span style=\"color: #dcaeea;\">rechunk<\/span>: <span style=\"color: #51afef;\">true<\/span>,\n        <span style=\"color: #dcaeea;\">to_supertypes<\/span>: <span style=\"color: #51afef;\">true<\/span>,\n    <span style=\"color: #c678dd;\">}<\/span>;\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">concat_metrics<\/span>: <span style=\"color: #ECBE7B;\">DataFrame<\/span> = concat<span style=\"color: #c678dd;\">(<\/span>metrics<span style=\"color: #c678dd; font-weight: bold;\">?<\/span>, concat_rules<span style=\"color: #c678dd;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>.collect<span style=\"color: #c678dd;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>;\n\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">search for the best split<\/span>\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">expr<\/span>: <span style=\"color: #ECBE7B;\">Expr<\/span> = col<span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98be65;\">\"metrics\"<\/span><span style=\"color: #c678dd;\">)<\/span>.lt_eq<span style=\"color: #c678dd;\">(<\/span>col<span style=\"color: #98be65;\">(<\/span><span style=\"color: #98be65;\">\"metrics\"<\/span><span style=\"color: #98be65;\">)<\/span>.min<span style=\"color: #98be65;\">()<\/span><span style=\"color: #c678dd;\">)<\/span>;\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">best_split<\/span>: <span style=\"color: #ECBE7B;\">DataFrame<\/span> = concat_metrics\n        .clone<span style=\"color: #c678dd;\">()<\/span>\n        .lazy<span style=\"color: #c678dd;\">()<\/span>\n        .filter<span style=\"color: #c678dd;\">(<\/span>expr<span style=\"color: #c678dd;\">)<\/span>\n        .select<span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98be65;\">[<\/span>col<span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #98be65;\">\"feature\"<\/span><span style=\"color: #a9a1e1;\">)<\/span>, col<span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #98be65;\">\"split\"<\/span><span style=\"color: #a9a1e1;\">)<\/span>, col<span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #98be65;\">\"metrics\"<\/span><span style=\"color: #a9a1e1;\">)<\/span><span style=\"color: #98be65;\">]<\/span><span style=\"color: #c678dd;\">)<\/span>\n        .collect<span style=\"color: #c678dd;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>;\n\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">chosen_features<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">String<\/span><span style=\"color: #c678dd;\">&gt;<\/span> = best_split\n        .column<span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98be65;\">\"feature\"<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>\n        .<span style=\"color: #ECBE7B;\">str<\/span><span style=\"color: #c678dd;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>\n        .iter<span style=\"color: #c678dd;\">()<\/span>\n        .flatten<span style=\"color: #c678dd;\">()<\/span>\n        .map<span style=\"color: #c678dd;\">(<\/span>|name| <span style=\"color: #98be65;\">&lt;<\/span>&amp; <span style=\"color: #ECBE7B;\">str<\/span> <span style=\"color: #51afef;\">as<\/span> <span style=\"color: #ECBE7B;\">Into<\/span><span style=\"color: #a9a1e1;\">&lt;<\/span><span style=\"color: #ECBE7B;\">String<\/span><span style=\"color: #a9a1e1;\">&gt;<\/span><span style=\"color: #98be65;\">&gt;<\/span>::into<span style=\"color: #98be65;\">(<\/span>name<span style=\"color: #98be65;\">)<\/span><span style=\"color: #c678dd;\">)<\/span>\n        .collect<span style=\"color: #c678dd;\">()<\/span>;\n\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">chosen_split_point<\/span>: <span style=\"color: #ECBE7B;\">f64<\/span> = best_split.column<span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98be65;\">\"split\"<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>.<span style=\"color: #ECBE7B;\">f64<\/span><span style=\"color: #c678dd;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>.get<span style=\"color: #c678dd;\">(<\/span><span style=\"color: #da8548; font-weight: bold;\">0<\/span><span style=\"color: #c678dd;\">)<\/span>.unwrap<span style=\"color: #c678dd;\">()<\/span>;\n\n    <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">split_metric<\/span>: <span style=\"color: #ECBE7B;\">f64<\/span> = best_split.column<span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98be65;\">\"metrics\"<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>.<span style=\"color: #ECBE7B;\">f64<\/span><span style=\"color: #c678dd;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>.get<span style=\"color: #c678dd;\">(<\/span><span style=\"color: #da8548; font-weight: bold;\">0<\/span><span style=\"color: #c678dd;\">)<\/span>.unwrap<span style=\"color: #c678dd;\">()<\/span>;\n    <span style=\"color: #ECBE7B;\">Ok<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #ECBE7B;\">Rule<\/span> <span style=\"color: #98be65;\">{<\/span>\n        <span style=\"color: #dcaeea;\">dimension<\/span>: chosen_features\n            .get<span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #da8548; font-weight: bold;\">0<\/span><span style=\"color: #a9a1e1;\">)<\/span>\n            .unwrap<span style=\"color: #a9a1e1;\">()<\/span>\n            .to_string<span style=\"color: #a9a1e1;\">()<\/span>,\n        <span style=\"color: #dcaeea;\">cutoff<\/span>: chosen_split_point,\n        <span style=\"color: #dcaeea;\">metric<\/span>: split_metric,\n    <span style=\"color: #98be65;\">}<\/span><span style=\"color: #c678dd;\">)<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"outline-container-orgc6225d7\" class=\"outline-2\">\n<h2 id=\"orgc6225d7\">Stopping rules<\/h2>\n<div class=\"outline-text-2\" id=\"text-orgc6225d7\">\n<p> We are going to create a tree using a greedy algorithm, i.e. one node at a time, recursively; while this does not guarantees to have the best possible result, it makes this problem treatable. <\/p>\n\n<p> Until when should this iteration go? <\/p>\n\n<p> I&rsquo;d like to implement three basic stopping rules: <\/p>\n\n<ul class=\"org-ul\">\n<li>the current node contains one class only<\/li>\n<li>the current level is equal to the maximum depth provided by the user<\/li>\n<li>the current node contains less elements than the minimum decided by the user<\/li>\n<\/ul>\n\n<p> It is reasonable to split multiple time along the same axis for continuous features, but I&rsquo;d like to see the effect of dropping a feature once used so I will leave this as a build option <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\">        <span style=\"color: #51afef;\">if<\/span> <span style=\"color: #51afef;\">(<\/span>!current_features.is_empty<span style=\"color: #c678dd;\">()<\/span><span style=\"color: #51afef;\">)<\/span> &amp;&amp; <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">exhausted features<\/span>\n            <span style=\"color: #51afef;\">(<\/span>confidence &lt; <span style=\"color: #da8548; font-weight: bold;\">1.0<\/span><span style=\"color: #51afef;\">)<\/span> &amp;&amp; <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">all elements belong to one category<\/span>\n            <span style=\"color: #51afef;\">(<\/span>data.shape<span style=\"color: #c678dd;\">()<\/span>.<span style=\"color: #da8548; font-weight: bold;\">0<\/span> &gt; <span style=\"color: #51afef;\">self<\/span>.min_size<span style=\"color: #51afef;\">)<\/span> &amp;&amp; <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">size is below minimum threshold<\/span>\n            <span style=\"color: #51afef;\">(<\/span>level &lt;= <span style=\"color: #51afef;\">self<\/span>.max_level<span style=\"color: #51afef;\">){<\/span> <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">maximum depth reached<\/span>\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"outline-container-org1747ee4\" class=\"outline-2\">\n<h2 id=\"org1747ee4\">Builder pattern in Rust<\/h2>\n<div class=\"outline-text-2\" id=\"text-org1747ee4\">\n<p> Rust does not have optional parameter with default values; to emulate this functionality the &ldquo;builder&rdquo; pattern is used. <\/p>\n\n<p> This pattern consist in the following: <\/p>\n\n<ul class=\"org-ul\">\n<li>create a default constructor for your structure which require only mandatory inputs<\/li>\n<li>add a method per each optional field which receives the actual structure (so takes ownership) and returns it mutated\n\n<ul class=\"org-ul\">\n<li>this allows to create chains of calls and make sure that there are no other parts of the code which may access the same structure while we are setting it up<\/li>\n<\/ul><\/li>\n<\/ul>\n\n<p> In our case we may want to store all the relevant tree creation options: the following are mandatory: <\/p>\n\n<ul class=\"org-ul\">\n<li>the names of the features<\/li>\n<li>the name of the target column<\/li>\n<\/ul>\n\n<p> The following are optional: <\/p>\n\n<ul class=\"org-ul\">\n<li>the maximum depth of the tree (we may set the default to 3)<\/li>\n<li>if we want to reuse all features after each split (usually true)<\/li>\n<li>the minimum size of a dataframe: only larger dataframes will be splitted<\/li>\n<\/ul>\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\">\n<span style=\"color: #51afef; font-weight: bold;\">#<\/span><span style=\"color: #51afef; font-weight: bold;\">[<\/span><span style=\"color: #51afef; font-weight: bold;\">derive<\/span><span style=\"color: #c678dd; font-weight: bold;\">(<\/span><span style=\"color: #51afef; font-weight: bold;\">Debug<\/span><span style=\"color: #c678dd; font-weight: bold;\">)<\/span><span style=\"color: #51afef; font-weight: bold;\">]<\/span>\n<span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">struct<\/span> <span style=\"color: #ECBE7B;\">DTreeBuilder<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #51afef;\">&gt;{<\/span>\n    <span style=\"color: #dcaeea;\">max_level<\/span>: <span style=\"color: #ECBE7B;\">usize<\/span>,\n    <span style=\"color: #dcaeea;\">min_size<\/span>: <span style=\"color: #ECBE7B;\">usize<\/span>,\n    <span style=\"color: #dcaeea;\">features<\/span>: <span style=\"color: #ECBE7B;\">HashSet<\/span><span style=\"color: #c678dd;\">&lt;<\/span>&amp; '<span style=\"color: #dcaeea;\">a<\/span> <span style=\"color: #ECBE7B;\">str<\/span><span style=\"color: #c678dd;\">&gt;<\/span>,\n    <span style=\"color: #dcaeea;\">target<\/span>: &amp; '<span style=\"color: #dcaeea;\">a<\/span> <span style=\"color: #ECBE7B;\">str<\/span>,\n    <span style=\"color: #dcaeea;\">reuse_features<\/span>: <span style=\"color: #ECBE7B;\">bool<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">uses a struct to define trees constraints<\/span>\n<span style=\"color: #51afef;\">impl<\/span> <span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #51afef;\">&gt;<\/span><span style=\"color: #ECBE7B;\">DTreeBuilder<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #51afef;\">&gt;<\/span> <span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">new<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #dcaeea;\">features<\/span>: <span style=\"color: #ECBE7B;\">HashSet<\/span><span style=\"color: #98be65;\">&lt;<\/span>&amp; '<span style=\"color: #dcaeea;\">a<\/span> <span style=\"color: #ECBE7B;\">str<\/span><span style=\"color: #98be65;\">&gt;<\/span>, <span style=\"color: #dcaeea;\">target<\/span> : &amp; '<span style=\"color: #dcaeea;\">a<\/span> <span style=\"color: #ECBE7B;\">str<\/span><span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #ECBE7B;\">DTreeBuilder<\/span><span style=\"color: #c678dd;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #c678dd;\">&gt;{<\/span>\n        <span style=\"color: #ECBE7B;\">DTreeBuilder<\/span><span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #dcaeea;\">max_level<\/span>: <span style=\"color: #da8548; font-weight: bold;\">3<\/span>,\n            <span style=\"color: #dcaeea;\">min_size<\/span>: <span style=\"color: #da8548; font-weight: bold;\">1<\/span>,\n            features,\n            target,\n            <span style=\"color: #dcaeea;\">reuse_features<\/span>: <span style=\"color: #51afef;\">true<\/span>\n        <span style=\"color: #98be65;\">}<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">set_max_level<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #51afef;\">self<\/span>, <span style=\"color: #dcaeea;\">max_level<\/span>: <span style=\"color: #ECBE7B;\">usize<\/span><span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #ECBE7B;\">DTreeBuilder<\/span><span style=\"color: #c678dd;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #c678dd;\">&gt;{<\/span>\n        <span style=\"color: #51afef;\">self<\/span>.max_level = max_level;\n        <span style=\"color: #51afef;\">self<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">set_min_size<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #51afef;\">self<\/span>, <span style=\"color: #dcaeea;\">min_size<\/span>: <span style=\"color: #ECBE7B;\">usize<\/span><span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #ECBE7B;\">DTreeBuilder<\/span><span style=\"color: #c678dd;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #c678dd;\">&gt;{<\/span>\n        <span style=\"color: #51afef;\">self<\/span>.min_size = min_size;\n        <span style=\"color: #51afef;\">self<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">set_reuse_features<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #51afef;\">self<\/span>, <span style=\"color: #dcaeea;\">reuse_features<\/span> : <span style=\"color: #ECBE7B;\">bool<\/span><span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #ECBE7B;\">DTreeBuilder<\/span><span style=\"color: #c678dd;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #c678dd;\">&gt;{<\/span>\n        <span style=\"color: #51afef;\">self<\/span>.reuse_features = reuse_features;\n        <span style=\"color: #51afef;\">self<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"outline-container-org9a70d86\" class=\"outline-2\">\n<h2 id=\"org9a70d86\">Iterative node building<\/h2>\n<div class=\"outline-text-2\" id=\"text-org9a70d86\">\n<p> There is a public access point which receives only the original training dataset <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\"><span style=\"color: #51afef;\">impl<\/span> <span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #51afef;\">&gt;<\/span><span style=\"color: #ECBE7B;\">DTreeBuilder<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #51afef;\">&gt;<\/span> <span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">...<\/span>\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">build<\/span><span style=\"color: #c678dd;\">(<\/span>\n        &amp; <span style=\"color: #51afef;\">self<\/span>,\n        <span style=\"color: #dcaeea;\">data<\/span>: &amp; <span style=\"color: #ECBE7B;\">DataFrame<\/span>,\n    <span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #ECBE7B;\">PolarsResult<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #a9a1e1;\">btree<\/span>::<span style=\"color: #ECBE7B;\">Tree<\/span><span style=\"color: #98be65;\">&lt;<\/span><span style=\"color: #ECBE7B;\">Decision<\/span><span style=\"color: #98be65;\">&gt;<\/span><span style=\"color: #c678dd;\">&gt;<\/span> <span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">current_features<\/span> = <span style=\"color: #51afef;\">if<\/span> !<span style=\"color: #51afef;\">self<\/span>.reuse_features <span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">feats<\/span> = <span style=\"color: #51afef;\">self<\/span>.features.clone<span style=\"color: #a9a1e1;\">()<\/span>;\n            <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #a9a1e1;\">(<\/span>feats<span style=\"color: #a9a1e1;\">)<\/span>\n        <span style=\"color: #98be65;\">}<\/span><span style=\"color: #51afef;\">else<\/span><span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #ECBE7B;\">None<\/span>\n        <span style=\"color: #98be65;\">}<\/span>;\n        <span style=\"color: #c678dd;\">println!<\/span><span style=\"color: #98be65;\">(<\/span><span style=\"color: #98be65;\">\"<\/span><span style=\"color: #98be65; font-style: italic;\">{1:-&gt;0$}{2:?}{1:-&lt;0$}<\/span><span style=\"color: #98be65;\">\"<\/span>, <span style=\"color: #da8548; font-weight: bold;\">20<\/span>, <span style=\"color: #98be65;\">\"\\n\"<\/span>, <span style=\"color: #51afef;\">self<\/span><span style=\"color: #98be65;\">)<\/span>;\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">root<\/span> = <span style=\"color: #51afef;\">self<\/span>.build_node<span style=\"color: #98be65;\">(<\/span>data, <span style=\"color: #da8548; font-weight: bold;\">1<\/span>, &amp; current_features<span style=\"color: #98be65;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>;\n        <span style=\"color: #ECBE7B;\">Ok<\/span><span style=\"color: #98be65;\">(<\/span><span style=\"color: #a9a1e1;\">btree<\/span>::<span style=\"color: #ECBE7B;\">Tree<\/span>::from_node<span style=\"color: #a9a1e1;\">(<\/span>root<span style=\"color: #a9a1e1;\">)<\/span><span style=\"color: #98be65;\">)<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">...<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n<\/pre>\n<\/div>\n\n<p> Until a stopping condition is met for each node iteratively all features are evaluated to find the most effective split according to our current metrics (Gini impurity index) than <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\"><span style=\"color: #51afef;\">impl<\/span> <span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #51afef;\">&gt;<\/span><span style=\"color: #ECBE7B;\">DTreeBuilder<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span><span style=\"color: #51afef;\">&gt;<\/span> <span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">...<\/span>\n    <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">build_node<\/span><span style=\"color: #c678dd;\">(<\/span>\n        &amp; <span style=\"color: #51afef;\">self<\/span>,\n        <span style=\"color: #dcaeea;\">data<\/span>: &amp; <span style=\"color: #ECBE7B;\">DataFrame<\/span>,\n        <span style=\"color: #dcaeea;\">level<\/span>: <span style=\"color: #ECBE7B;\">usize<\/span>, <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">tree depth<\/span>\n        <span style=\"color: #dcaeea;\">features<\/span>: &amp; <span style=\"color: #ECBE7B;\">Option<\/span><span style=\"color: #98be65;\">&lt;<\/span><span style=\"color: #ECBE7B;\">HashSet<\/span><span style=\"color: #a9a1e1;\">&lt;<\/span>&amp; <span style=\"color: #ECBE7B;\">str<\/span><span style=\"color: #a9a1e1;\">&gt;<\/span><span style=\"color: #98be65;\">&gt;<\/span>, <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">optionally used to remove features<\/span>\n    <span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #ECBE7B;\">PolarsResult<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #a9a1e1;\">btree<\/span>::<span style=\"color: #ECBE7B;\">Node<\/span><span style=\"color: #98be65;\">&lt;<\/span><span style=\"color: #ECBE7B;\">Decision<\/span><span style=\"color: #98be65;\">&gt;<\/span><span style=\"color: #c678dd;\">&gt;<\/span> <span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">prediction<\/span> = predict_majority_dataframe<span style=\"color: #98be65;\">(<\/span>data, <span style=\"color: #51afef;\">self<\/span>.target<span style=\"color: #98be65;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>;\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">confidence<\/span> = prediction.confidence;\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #dcaeea;\">node<\/span> = <span style=\"color: #a9a1e1;\">btree<\/span>::<span style=\"color: #ECBE7B;\">Node<\/span>::new<span style=\"color: #98be65;\">(<\/span>prediction<span style=\"color: #98be65;\">)<\/span>;\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">current_features<\/span> = features.clone<span style=\"color: #98be65;\">()<\/span>.unwrap_or<span style=\"color: #98be65;\">(<\/span><span style=\"color: #51afef;\">self<\/span>.features.clone<span style=\"color: #a9a1e1;\">()<\/span><span style=\"color: #98be65;\">)<\/span>;\n        <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">check stop conditions<\/span>\n        <span style=\"color: #51afef;\">if<\/span> <span style=\"color: #98be65;\">(<\/span>!current_features.is_empty<span style=\"color: #a9a1e1;\">()<\/span><span style=\"color: #98be65;\">)<\/span> &amp;&amp; <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">exhausted features<\/span>\n            <span style=\"color: #98be65;\">(<\/span>confidence &lt; <span style=\"color: #da8548; font-weight: bold;\">1.0<\/span><span style=\"color: #98be65;\">)<\/span> &amp;&amp; <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">all elements belong to one category<\/span>\n            <span style=\"color: #98be65;\">(<\/span>data.shape<span style=\"color: #a9a1e1;\">()<\/span>.<span style=\"color: #da8548; font-weight: bold;\">0<\/span> &gt; <span style=\"color: #51afef;\">self<\/span>.min_size<span style=\"color: #98be65;\">)<\/span> &amp;&amp; <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">size is below minimum threshold<\/span>\n            <span style=\"color: #98be65;\">(<\/span>level &lt;= <span style=\"color: #51afef;\">self<\/span>.max_level<span style=\"color: #98be65;\">){<\/span> <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">maximum depth reached<\/span>\n                <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">rule<\/span> = evaluate_best_split<span style=\"color: #a9a1e1;\">(<\/span>data, &amp; current_features, <span style=\"color: #51afef;\">self<\/span>.target<span style=\"color: #a9a1e1;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>;\n                <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">higher<\/span>: <span style=\"color: #ECBE7B;\">DataFrame<\/span> = data\n                    .clone<span style=\"color: #a9a1e1;\">()<\/span>\n                    .lazy<span style=\"color: #a9a1e1;\">()<\/span>\n                    .filter<span style=\"color: #a9a1e1;\">(<\/span>col<span style=\"color: #51afef;\">(<\/span>&amp; rule.dimension<span style=\"color: #51afef;\">)<\/span>.gt<span style=\"color: #51afef;\">(<\/span>rule.cutoff<span style=\"color: #51afef;\">)<\/span><span style=\"color: #a9a1e1;\">)<\/span>\n                    .collect<span style=\"color: #a9a1e1;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>;\n                <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">lower<\/span>: <span style=\"color: #ECBE7B;\">DataFrame<\/span> = data\n                    .clone<span style=\"color: #a9a1e1;\">()<\/span>\n                    .lazy<span style=\"color: #a9a1e1;\">()<\/span>\n                    .filter<span style=\"color: #a9a1e1;\">(<\/span>col<span style=\"color: #51afef;\">(<\/span>&amp; rule.dimension<span style=\"color: #51afef;\">)<\/span>.lt_eq<span style=\"color: #51afef;\">(<\/span>rule.cutoff<span style=\"color: #51afef;\">)<\/span><span style=\"color: #a9a1e1;\">)<\/span>\n                    .collect<span style=\"color: #a9a1e1;\">()<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>;\n                <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">remove features only if requested by the user<\/span>\n                <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">next_features<\/span> = <span style=\"color: #51afef;\">match<\/span> features <span style=\"color: #a9a1e1;\">{<\/span>\n                    <span style=\"color: #ECBE7B;\">None<\/span> =&gt; <span style=\"color: #ECBE7B;\">None<\/span>,\n                    <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #51afef;\">(<\/span>feats<span style=\"color: #51afef;\">)<\/span> =&gt; <span style=\"color: #51afef;\">{<\/span>\n                        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #dcaeea;\">reduced_features<\/span> =\n                            feats.clone<span style=\"color: #c678dd;\">()<\/span>;\n                        reduced_features.remove<span style=\"color: #c678dd;\">(<\/span>rule.dimension.as_str<span style=\"color: #98be65;\">()<\/span><span style=\"color: #c678dd;\">)<\/span>;\n                        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">feats_vec<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">String<\/span><span style=\"color: #c678dd;\">&gt;<\/span> = reduced_features\n                            .iter<span style=\"color: #c678dd;\">()<\/span>\n                            .map<span style=\"color: #c678dd;\">(<\/span>|s| s.to_string<span style=\"color: #98be65;\">()<\/span><span style=\"color: #c678dd;\">)<\/span>\n                            .collect<span style=\"color: #c678dd;\">()<\/span>;\n                        <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #c678dd;\">(<\/span>reduced_features<span style=\"color: #c678dd;\">)<\/span>\n                    <span style=\"color: #51afef;\">}<\/span>\n                <span style=\"color: #a9a1e1;\">}<\/span>;\n                node.value.rule = <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #a9a1e1;\">(<\/span>rule<span style=\"color: #a9a1e1;\">)<\/span>;\n                <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">creates leaves<\/span>\n                node.left = <span style=\"color: #51afef;\">self<\/span>\n                    .build_node<span style=\"color: #a9a1e1;\">(<\/span>&amp; higher, level + <span style=\"color: #da8548; font-weight: bold;\">1<\/span>, &amp; next_features<span style=\"color: #a9a1e1;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>\n                    .into<span style=\"color: #a9a1e1;\">()<\/span>;\n                node.right = <span style=\"color: #51afef;\">self<\/span>\n                    .build_node<span style=\"color: #a9a1e1;\">(<\/span>&amp; lower, level + <span style=\"color: #da8548; font-weight: bold;\">1<\/span>, &amp; next_features<span style=\"color: #a9a1e1;\">)<\/span><span style=\"color: #c678dd; font-weight: bold;\">?<\/span>\n                    .into<span style=\"color: #a9a1e1;\">()<\/span>;\n            <span style=\"color: #98be65;\">}<\/span>\n        <span style=\"color: #ECBE7B;\">Ok<\/span><span style=\"color: #98be65;\">(<\/span>node<span style=\"color: #98be65;\">)<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n    <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">...<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"outline-container-orgc3a2c12\" class=\"outline-2\">\n<h2 id=\"orgc3a2c12\">Dumping the tree<\/h2>\n<div class=\"outline-text-2\" id=\"text-orgc3a2c12\">\n<\/div>\n<div id=\"outline-container-org6b75931\" class=\"outline-3\">\n<h3 id=\"org6b75931\">Pre-order depth first traversal<\/h3>\n<div class=\"outline-text-3\" id=\"text-org6b75931\">\n<p> in a previoust <a href=\"https:\/\/noiseonthenet.space\/noise\/2024\/04\/climbing-a-binary-tree\/\">post<\/a> I show how to create a depth first traversal algorithm. <\/p>\n\n<p> To be more specific it was a <b>post-order<\/b> traversal: you can find more details about the kind of traversal algorithms <a href=\"https:\/\/en.wikipedia.org\/wiki\/Tree_traversal\">in this Wikipedia page<\/a>. <\/p>\n\n<p> To draw our tree we now need a <b>pre-order<\/b> traversal iterator: <a href=\"https:\/\/noiseonthenet.space\/noise\/2024\/04\/climbing-a-binary-tree\/#comment-11\">Caleb Sander Mateos<\/a> suggested me in a comment how to use a stack to implement this kind of traversal: my code follows <\/p>\n\n<p> I added some more useful information to the iterator result <\/p>\n\n<ul class=\"org-ul\">\n<li>the current node depth<\/li>\n<li>its number according to the binary position described <a href=\"https:\/\/noiseonthenet.space\/noise\/2024\/03\/stacking-bits\/\">here<\/a><\/li>\n<li>a boolean describing if the current node is a leaf<\/li>\n<\/ul>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\"><span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">struct<\/span> <span style=\"color: #ECBE7B;\">PreOrderTraversalIter<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span>, <span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #51afef;\">&gt;{<\/span>\n    <span style=\"color: #dcaeea;\">stack<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">TreeStackItem<\/span><span style=\"color: #98be65;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span>, <span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #98be65;\">&gt;<\/span><span style=\"color: #c678dd;\">&gt;<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">struct<\/span> <span style=\"color: #ECBE7B;\">TreeItem<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span>, <span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #51afef;\">&gt;{<\/span>\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #dcaeea;\">id<\/span>: <span style=\"color: #ECBE7B;\">usize<\/span>,\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #dcaeea;\">level<\/span>: <span style=\"color: #ECBE7B;\">usize<\/span>,\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #dcaeea;\">value<\/span>: &amp; '<span style=\"color: #dcaeea;\">a<\/span> <span style=\"color: #ECBE7B;\">T<\/span>,\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #dcaeea;\">leaf<\/span>: <span style=\"color: #ECBE7B;\">bool<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<span style=\"color: #51afef;\">struct<\/span> <span style=\"color: #ECBE7B;\">TreeStackItem<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span>, <span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #51afef;\">&gt;{<\/span>\n    <span style=\"color: #dcaeea;\">id<\/span>: <span style=\"color: #ECBE7B;\">usize<\/span>,\n    <span style=\"color: #dcaeea;\">level<\/span>: <span style=\"color: #ECBE7B;\">usize<\/span>,\n    <span style=\"color: #dcaeea;\">node<\/span>: &amp; '<span style=\"color: #dcaeea;\">a<\/span> <span style=\"color: #ECBE7B;\">Node<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #c678dd;\">&gt;<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<span style=\"color: #51afef;\">impl<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span>, <span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #51afef;\">&gt;<\/span> <span style=\"color: #ECBE7B;\">PreOrderTraversalIter<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span>, <span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #51afef;\">&gt;{<\/span>\n    <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">new<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #dcaeea;\">tree<\/span>: &amp; '<span style=\"color: #dcaeea;\">a<\/span> <span style=\"color: #ECBE7B;\">Tree<\/span><span style=\"color: #98be65;\">&lt;<\/span><span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #98be65;\">&gt;<\/span><span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #ECBE7B;\">PreOrderTraversalIter<\/span><span style=\"color: #c678dd;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span>, <span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #c678dd;\">&gt;{<\/span>\n        <span style=\"color: #51afef;\">match<\/span> tree.root <span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #ECBE7B;\">None<\/span> =&gt; <span style=\"color: #ECBE7B;\">PreOrderTraversalIter<\/span> <span style=\"color: #a9a1e1;\">{<\/span> <span style=\"color: #dcaeea;\">stack<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span>::new<span style=\"color: #51afef;\">()<\/span> <span style=\"color: #a9a1e1;\">}<\/span>,\n            <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #51afef;\">ref<\/span> <span style=\"color: #dcaeea;\">node<\/span><span style=\"color: #a9a1e1;\">)<\/span> =&gt; <span style=\"color: #ECBE7B;\">PreOrderTraversalIter<\/span> <span style=\"color: #a9a1e1;\">{<\/span>\n                <span style=\"color: #dcaeea;\">stack<\/span>: <span style=\"color: #51afef; font-weight: bold;\">vec!<\/span><span style=\"color: #51afef;\">[<\/span>\n                    <span style=\"color: #ECBE7B;\">TreeStackItem<\/span><span style=\"color: #c678dd;\">{<\/span>\n                        <span style=\"color: #dcaeea;\">id<\/span>: <span style=\"color: #da8548; font-weight: bold;\">1<\/span>,\n                        <span style=\"color: #dcaeea;\">level<\/span>: <span style=\"color: #da8548; font-weight: bold;\">1<\/span>,\n                        <span style=\"color: #dcaeea;\">node<\/span>: &amp; node\n                    <span style=\"color: #c678dd;\">}<\/span><span style=\"color: #51afef;\">]<\/span>,\n            <span style=\"color: #a9a1e1;\">}<\/span>,\n        <span style=\"color: #98be65;\">}<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<span style=\"color: #51afef;\">impl<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span>, <span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #51afef;\">&gt;<\/span> <span style=\"color: #ECBE7B;\">Iterator<\/span> <span style=\"color: #51afef;\">for<\/span> <span style=\"color: #ECBE7B;\">PreOrderTraversalIter<\/span><span style=\"color: #51afef;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span>, <span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #51afef;\">&gt;{<\/span>\n    <span style=\"color: #51afef;\">type<\/span> <span style=\"color: #ECBE7B;\">Item<\/span> = <span style=\"color: #ECBE7B;\">TreeItem<\/span><span style=\"color: #c678dd;\">&lt;<\/span>'<span style=\"color: #dcaeea;\">a<\/span>, <span style=\"color: #ECBE7B;\">T<\/span><span style=\"color: #c678dd;\">&gt;<\/span>;\n    <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">next<\/span><span style=\"color: #c678dd;\">(<\/span>&amp; <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #51afef;\">self<\/span><span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #ECBE7B;\">Option<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">Self<\/span>::<span style=\"color: #ECBE7B;\">Item<\/span><span style=\"color: #c678dd;\">&gt;<\/span> <span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #51afef;\">if<\/span> <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #98be65;\">(<\/span>item<span style=\"color: #98be65;\">)<\/span> = <span style=\"color: #51afef;\">self<\/span>.stack.pop<span style=\"color: #98be65;\">()<\/span> <span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #dcaeea;\">leaf<\/span>: <span style=\"color: #ECBE7B;\">bool<\/span> = <span style=\"color: #51afef;\">true<\/span>;\n            <span style=\"color: #51afef;\">if<\/span> <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #51afef;\">ref<\/span> <span style=\"color: #dcaeea;\">left<\/span><span style=\"color: #a9a1e1;\">)<\/span> = item.node.left<span style=\"color: #a9a1e1;\">{<\/span>\n                <span style=\"color: #51afef;\">self<\/span>.stack.push<span style=\"color: #51afef;\">(<\/span>\n                    <span style=\"color: #ECBE7B;\">TreeStackItem<\/span><span style=\"color: #c678dd;\">{<\/span>\n                        <span style=\"color: #dcaeea;\">id<\/span>: item.id &lt;&lt; <span style=\"color: #da8548; font-weight: bold;\">1<\/span>,\n                        <span style=\"color: #dcaeea;\">level<\/span>: item.level + <span style=\"color: #da8548; font-weight: bold;\">1<\/span>,\n                        <span style=\"color: #dcaeea;\">node<\/span>: &amp; left\n                    <span style=\"color: #c678dd;\">}<\/span><span style=\"color: #51afef;\">)<\/span>;\n                leaf = <span style=\"color: #51afef;\">false<\/span>;\n            <span style=\"color: #a9a1e1;\">}<\/span>\n            <span style=\"color: #51afef;\">if<\/span> <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #51afef;\">ref<\/span> <span style=\"color: #dcaeea;\">right<\/span><span style=\"color: #a9a1e1;\">)<\/span> = item.node.right<span style=\"color: #a9a1e1;\">{<\/span>\n                <span style=\"color: #51afef;\">self<\/span>.stack.push<span style=\"color: #51afef;\">(<\/span>\n                    <span style=\"color: #ECBE7B;\">TreeStackItem<\/span><span style=\"color: #c678dd;\">{<\/span>\n                        <span style=\"color: #dcaeea;\">id<\/span>: <span style=\"color: #98be65;\">(<\/span>item.id &lt;&lt; <span style=\"color: #da8548; font-weight: bold;\">1<\/span><span style=\"color: #98be65;\">)<\/span> + <span style=\"color: #da8548; font-weight: bold;\">1<\/span>,\n                        <span style=\"color: #dcaeea;\">level<\/span>: item.level + <span style=\"color: #da8548; font-weight: bold;\">1<\/span>,\n                        <span style=\"color: #dcaeea;\">node<\/span>: &amp; right\n                    <span style=\"color: #c678dd;\">}<\/span><span style=\"color: #51afef;\">)<\/span>;\n                leaf = <span style=\"color: #51afef;\">false<\/span>;\n            <span style=\"color: #a9a1e1;\">}<\/span>\n            <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #a9a1e1;\">(<\/span>\n                <span style=\"color: #ECBE7B;\">TreeItem<\/span><span style=\"color: #51afef;\">{<\/span>\n                    <span style=\"color: #dcaeea;\">id<\/span>: item.id,\n                    <span style=\"color: #dcaeea;\">level<\/span>: item.level,\n                    <span style=\"color: #dcaeea;\">value<\/span>: &amp; item.node.value,\n                    leaf\n                <span style=\"color: #51afef;\">}<\/span><span style=\"color: #a9a1e1;\">)<\/span>\n        <span style=\"color: #98be65;\">}<\/span><span style=\"color: #51afef;\">else<\/span><span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #ECBE7B;\">None<\/span>\n        <span style=\"color: #98be65;\">}<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"outline-container-orgb72ba6a\" class=\"outline-3\">\n<h3 id=\"orgb72ba6a\">creating a Dot DSL reification<\/h3>\n<div class=\"outline-text-3\" id=\"text-orgb72ba6a\">\n<p> This is an example of the chart of a sorting tree: <\/p>\n\n<div id=\"orgd9c1f18\" class=\"figure\"> <p><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_example_tree.png?ssl=1\" alt=\"post017_example_tree.png\" \/> <\/p> <\/div>\n\n<p> I chose <a href=\"https:\/\/graphviz.org\/\">graphviz<\/a> to automatically generate a chart of my tree graph, I used a subset of its graph language dot. <\/p>\n\n<p> In these cases the best way for me to create a language generator is to choose which parts of its grammar to transform into data object; i chose: <\/p>\n\n<ul class=\"org-ul\">\n<li>nodes<\/li>\n<li>edges<\/li>\n<li>ranks to put nodes at the same level in the same row<\/li>\n<\/ul>\n\n<p> A rank is actually a list of node names, i.e. strings, thus a vector of strings should be enough, but we need a specialized representation so I used a wrapper type <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\"><span style=\"color: #51afef;\">struct<\/span> <span style=\"color: #ECBE7B;\">DotNode<\/span><span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #dcaeea;\">name<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n    <span style=\"color: #dcaeea;\">label<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n    <span style=\"color: #dcaeea;\">shape<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n    <span style=\"color: #dcaeea;\">style<\/span>: <span style=\"color: #ECBE7B;\">Option<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">String<\/span><span style=\"color: #c678dd;\">&gt;<\/span>,\n    <span style=\"color: #dcaeea;\">fillcolor<\/span>: <span style=\"color: #ECBE7B;\">Option<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">String<\/span><span style=\"color: #c678dd;\">&gt;<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<span style=\"color: #51afef;\">struct<\/span> <span style=\"color: #ECBE7B;\">DotEdge<\/span><span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #dcaeea;\">first<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n    <span style=\"color: #dcaeea;\">second<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n    <span style=\"color: #dcaeea;\">label<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">wrapper type<\/span>\n<span style=\"color: #51afef; font-weight: bold;\">#<\/span><span style=\"color: #51afef; font-weight: bold;\">[<\/span><span style=\"color: #51afef; font-weight: bold;\">derive<\/span><span style=\"color: #c678dd; font-weight: bold;\">(<\/span><span style=\"color: #51afef; font-weight: bold;\">Default<\/span><span style=\"color: #c678dd; font-weight: bold;\">)<\/span><span style=\"color: #51afef; font-weight: bold;\">]<\/span>\n<span style=\"color: #51afef;\">struct<\/span> <span style=\"color: #ECBE7B;\">DotRank<\/span><span style=\"color: #51afef;\">(<\/span><span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">String<\/span><span style=\"color: #c678dd;\">&gt;<\/span><span style=\"color: #51afef;\">)<\/span>;\n\n<span style=\"color: #51afef;\">impl<\/span> <span style=\"color: #ECBE7B;\">DotRank<\/span><span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">new<\/span><span style=\"color: #c678dd;\">()<\/span> -&gt; <span style=\"color: #ECBE7B;\">DotRank<\/span><span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #ECBE7B;\">DotRank<\/span><span style=\"color: #98be65;\">(<\/span>\n            <span style=\"color: #ECBE7B;\">Vec<\/span>::new<span style=\"color: #a9a1e1;\">()<\/span>\n        <span style=\"color: #98be65;\">)<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n<\/pre>\n<\/div>\n\n<p> Per each one I created its text representation following dot grammar <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\">\n<span style=\"color: #51afef;\">impl<\/span> <span style=\"color: #ECBE7B;\">Display<\/span> <span style=\"color: #51afef;\">for<\/span> <span style=\"color: #ECBE7B;\">DotNode<\/span><span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">fmt<\/span><span style=\"color: #c678dd;\">(<\/span>&amp; <span style=\"color: #51afef;\">self<\/span>, <span style=\"color: #dcaeea;\">f<\/span>: &amp; <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #a9a1e1;\">fmt<\/span>::<span style=\"color: #ECBE7B;\">Formatter<\/span><span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #a9a1e1;\">fmt<\/span>::<span style=\"color: #ECBE7B;\">Result<\/span> <span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">style<\/span>: <span style=\"color: #ECBE7B;\">String<\/span> = <span style=\"color: #51afef;\">match<\/span> <span style=\"color: #51afef;\">self<\/span>.style <span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #ECBE7B;\">None<\/span> =&gt; <span style=\"color: #98be65;\">\"\"<\/span>.into<span style=\"color: #a9a1e1;\">()<\/span>,\n            <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #51afef;\">ref<\/span> <span style=\"color: #dcaeea;\">kind<\/span><span style=\"color: #a9a1e1;\">)<\/span> =&gt; <span style=\"color: #c678dd;\">format!<\/span><span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #98be65;\">\", style=\\\"{}\\\"\"<\/span>,kind<span style=\"color: #a9a1e1;\">)<\/span>\n        <span style=\"color: #98be65;\">}<\/span>;\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">fillcolor<\/span>: <span style=\"color: #ECBE7B;\">String<\/span> = <span style=\"color: #51afef;\">match<\/span> <span style=\"color: #51afef;\">self<\/span>.fillcolor <span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #ECBE7B;\">None<\/span> =&gt; <span style=\"color: #98be65;\">\"\"<\/span>.into<span style=\"color: #a9a1e1;\">()<\/span>,\n            <span style=\"color: #ECBE7B;\">Some<\/span><span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #51afef;\">ref<\/span> <span style=\"color: #dcaeea;\">kind<\/span><span style=\"color: #a9a1e1;\">)<\/span> =&gt; <span style=\"color: #c678dd;\">format!<\/span><span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #98be65;\">\", fillcolor=\\\"{}\\\"\"<\/span>,kind<span style=\"color: #a9a1e1;\">)<\/span>\n        <span style=\"color: #98be65;\">}<\/span>;\n        <span style=\"color: #c678dd;\">write!<\/span><span style=\"color: #98be65;\">(<\/span>f,<span style=\"color: #98be65;\">\"<\/span><span style=\"color: #98be65; font-style: italic;\">{}<\/span><span style=\"color: #98be65;\"> [label=\\\"{}\\\", shape=\\\"{}\\\"{}{}];\"<\/span>,<span style=\"color: #51afef;\">self<\/span>.name, <span style=\"color: #51afef;\">self<\/span>.label, <span style=\"color: #51afef;\">self<\/span>.shape, style, fillcolor<span style=\"color: #98be65;\">)<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n\n<span style=\"color: #51afef;\">impl<\/span> <span style=\"color: #ECBE7B;\">Display<\/span> <span style=\"color: #51afef;\">for<\/span> <span style=\"color: #ECBE7B;\">DotEdge<\/span><span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">fmt<\/span><span style=\"color: #c678dd;\">(<\/span>&amp; <span style=\"color: #51afef;\">self<\/span>, <span style=\"color: #dcaeea;\">f<\/span>: &amp; <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #a9a1e1;\">fmt<\/span>::<span style=\"color: #ECBE7B;\">Formatter<\/span><span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #a9a1e1;\">fmt<\/span>::<span style=\"color: #ECBE7B;\">Result<\/span> <span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #c678dd;\">write!<\/span><span style=\"color: #98be65;\">(<\/span>f,<span style=\"color: #98be65;\">\"<\/span><span style=\"color: #98be65; font-style: italic;\">{}<\/span><span style=\"color: #98be65;\"> -&gt; <\/span><span style=\"color: #98be65; font-style: italic;\">{}<\/span><span style=\"color: #98be65;\"> [label=\\\"{}\\\"]\"<\/span>,<span style=\"color: #51afef;\">self<\/span>.first,<span style=\"color: #51afef;\">self<\/span>.second,<span style=\"color: #51afef;\">self<\/span>.label<span style=\"color: #98be65;\">)<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<span style=\"color: #51afef;\">impl<\/span> <span style=\"color: #ECBE7B;\">Display<\/span> <span style=\"color: #51afef;\">for<\/span> <span style=\"color: #ECBE7B;\">DotRank<\/span><span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">fmt<\/span><span style=\"color: #c678dd;\">(<\/span>&amp; <span style=\"color: #51afef;\">self<\/span>, <span style=\"color: #dcaeea;\">f<\/span>: &amp; <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #a9a1e1;\">fmt<\/span>::<span style=\"color: #ECBE7B;\">Formatter<\/span><span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #a9a1e1;\">fmt<\/span>::<span style=\"color: #ECBE7B;\">Result<\/span> <span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #c678dd;\">write!<\/span><span style=\"color: #98be65;\">(<\/span>f,<span style=\"color: #98be65;\">\"{{rank = same; <\/span><span style=\"color: #98be65; font-style: italic;\">{}<\/span><span style=\"color: #98be65;\">;}}\"<\/span>,<span style=\"color: #51afef;\">self<\/span>.<span style=\"color: #da8548; font-weight: bold;\">0<\/span>.join<span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #98be65;\">\"; \"<\/span><span style=\"color: #a9a1e1;\">)<\/span><span style=\"color: #98be65;\">)<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<\/pre>\n<\/div>\n\n<p> Finally I created a full object which contains all of these elements: <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\"><span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">struct<\/span> <span style=\"color: #ECBE7B;\">Dot<\/span><span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #dcaeea;\">nodes<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">DotNode<\/span><span style=\"color: #c678dd;\">&gt;<\/span>,\n    <span style=\"color: #dcaeea;\">edges<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">DotEdge<\/span><span style=\"color: #c678dd;\">&gt;<\/span>,\n    <span style=\"color: #dcaeea;\">ranks<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #c678dd;\">&lt;<\/span><span style=\"color: #ECBE7B;\">DotRank<\/span><span style=\"color: #c678dd;\">&gt;<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n<\/pre>\n<\/div>\n\n<p> To simplify the building I created a method to add each kind of element <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\"><span style=\"color: #51afef;\">impl<\/span> <span style=\"color: #ECBE7B;\">Dot<\/span><span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">new<\/span><span style=\"color: #c678dd;\">()<\/span> -&gt; <span style=\"color: #ECBE7B;\">Self<\/span><span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #ECBE7B;\">Dot<\/span><span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #dcaeea;\">nodes<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span>::new<span style=\"color: #a9a1e1;\">()<\/span>,\n            <span style=\"color: #dcaeea;\">edges<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span>::new<span style=\"color: #a9a1e1;\">()<\/span>,\n            <span style=\"color: #dcaeea;\">ranks<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span>::new<span style=\"color: #a9a1e1;\">()<\/span>,\n        <span style=\"color: #98be65;\">}<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">add_node<\/span><span style=\"color: #c678dd;\">(<\/span>\n        &amp; <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #51afef;\">self<\/span>,\n        <span style=\"color: #dcaeea;\">name<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n        <span style=\"color: #dcaeea;\">label<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n        <span style=\"color: #dcaeea;\">shape<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n        <span style=\"color: #dcaeea;\">style<\/span>: <span style=\"color: #ECBE7B;\">Option<\/span><span style=\"color: #98be65;\">&lt;<\/span><span style=\"color: #ECBE7B;\">String<\/span><span style=\"color: #98be65;\">&gt;<\/span>,\n        <span style=\"color: #dcaeea;\">fillcolor<\/span>: <span style=\"color: #ECBE7B;\">Option<\/span><span style=\"color: #98be65;\">&lt;<\/span><span style=\"color: #ECBE7B;\">String<\/span><span style=\"color: #98be65;\">&gt;<\/span>\n    <span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #c678dd;\">()<\/span> <span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">node<\/span> = <span style=\"color: #ECBE7B;\">DotNode<\/span><span style=\"color: #98be65;\">{<\/span>\n            name,\n            label,\n            shape,\n            style,\n            fillcolor\n        <span style=\"color: #98be65;\">}<\/span>;\n        <span style=\"color: #51afef;\">self<\/span>.nodes.push<span style=\"color: #98be65;\">(<\/span>node<span style=\"color: #98be65;\">)<\/span>;\n    <span style=\"color: #c678dd;\">}<\/span>\n\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">add_edge<\/span><span style=\"color: #c678dd;\">(<\/span>\n        &amp; <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #51afef;\">self<\/span>,\n        <span style=\"color: #dcaeea;\">first<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n        <span style=\"color: #dcaeea;\">second<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>,\n        <span style=\"color: #dcaeea;\">label<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>\n    <span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #c678dd;\">()<\/span> <span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">node<\/span> = <span style=\"color: #ECBE7B;\">DotEdge<\/span><span style=\"color: #98be65;\">{<\/span>first, second, label<span style=\"color: #98be65;\">}<\/span>;\n        <span style=\"color: #51afef;\">self<\/span>.edges.push<span style=\"color: #98be65;\">(<\/span>node<span style=\"color: #98be65;\">)<\/span>;\n    <span style=\"color: #c678dd;\">}<\/span>\n\n    <span style=\"color: #51afef;\">pub<\/span> <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">append_rank<\/span><span style=\"color: #c678dd;\">(<\/span>\n        &amp; <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #51afef;\">self<\/span>,\n        <span style=\"color: #dcaeea;\">index<\/span>: <span style=\"color: #ECBE7B;\">usize<\/span>,\n        <span style=\"color: #dcaeea;\">node<\/span>: <span style=\"color: #ECBE7B;\">String<\/span>\n    <span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #c678dd;\">(){<\/span>\n        <span style=\"color: #5B6268;\">\/\/<\/span><span style=\"color: #5B6268;\">ensure space<\/span>\n        <span style=\"color: #51afef;\">while<\/span> <span style=\"color: #51afef;\">self<\/span>.ranks.len<span style=\"color: #98be65;\">()<\/span> &lt;= index <span style=\"color: #98be65;\">{<\/span>\n            <span style=\"color: #51afef;\">self<\/span>.ranks.push<span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #ECBE7B;\">DotRank<\/span>::new<span style=\"color: #51afef;\">()<\/span><span style=\"color: #a9a1e1;\">)<\/span>\n        <span style=\"color: #98be65;\">}<\/span>\n        <span style=\"color: #5B6268;\">\/\/ <\/span><span style=\"color: #5B6268;\">update the rank at index adding the node<\/span>\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #dcaeea;\">bin<\/span> = take<span style=\"color: #98be65;\">(<\/span>&amp; <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #51afef;\">self<\/span>.ranks<span style=\"color: #a9a1e1;\">[<\/span>index<span style=\"color: #a9a1e1;\">]<\/span><span style=\"color: #98be65;\">)<\/span>;\n        bin.<span style=\"color: #da8548; font-weight: bold;\">0<\/span>.push<span style=\"color: #98be65;\">(<\/span>node<span style=\"color: #98be65;\">)<\/span>;\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #dcaeea;\">_<\/span> = replace<span style=\"color: #98be65;\">(<\/span>&amp; <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #51afef;\">self<\/span>.ranks<span style=\"color: #a9a1e1;\">[<\/span>index<span style=\"color: #a9a1e1;\">]<\/span>, bin<span style=\"color: #98be65;\">)<\/span>;\n    <span style=\"color: #c678dd;\">}<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n\n<\/pre>\n<\/div>\n\n<p> finally its transformation into a string <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-rust\" id=\"nil\"><span style=\"color: #51afef;\">impl<\/span> <span style=\"color: #ECBE7B;\">Display<\/span> <span style=\"color: #51afef;\">for<\/span> <span style=\"color: #ECBE7B;\">Dot<\/span><span style=\"color: #51afef;\">{<\/span>\n    <span style=\"color: #51afef;\">fn<\/span> <span style=\"color: #c678dd;\">fmt<\/span><span style=\"color: #c678dd;\">(<\/span>&amp; <span style=\"color: #51afef;\">self<\/span>, <span style=\"color: #dcaeea;\">f<\/span>: &amp; <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #a9a1e1;\">fmt<\/span>::<span style=\"color: #ECBE7B;\">Formatter<\/span><span style=\"color: #c678dd;\">)<\/span> -&gt; <span style=\"color: #a9a1e1;\">fmt<\/span>::<span style=\"color: #ECBE7B;\">Result<\/span> <span style=\"color: #c678dd;\">{<\/span>\n        <span style=\"color: #51afef;\">let<\/span> <span style=\"color: #51afef;\">mut<\/span> <span style=\"color: #dcaeea;\">graph<\/span>: <span style=\"color: #ECBE7B;\">Vec<\/span><span style=\"color: #98be65;\">&lt;<\/span><span style=\"color: #ECBE7B;\">String<\/span><span style=\"color: #98be65;\">&gt;<\/span>=<span style=\"color: #51afef; font-weight: bold;\">vec!<\/span><span style=\"color: #98be65;\">[<\/span><span style=\"color: #98be65;\">\"digraph {\"<\/span>.into<span style=\"color: #a9a1e1;\">()<\/span>,<span style=\"color: #98be65;\">\"rankdir = BT;\"<\/span>.into<span style=\"color: #a9a1e1;\">()<\/span>,<span style=\"color: #98be65;\">\"subgraph{\"<\/span>.into<span style=\"color: #a9a1e1;\">()<\/span><span style=\"color: #98be65;\">]<\/span>;\n        <span style=\"color: #51afef;\">for<\/span> <span style=\"color: #dcaeea;\">node<\/span> <span style=\"color: #51afef;\">in<\/span> &amp; <span style=\"color: #51afef;\">self<\/span>.nodes<span style=\"color: #98be65;\">{<\/span>\n            graph.push<span style=\"color: #a9a1e1;\">(<\/span>node.to_string<span style=\"color: #51afef;\">()<\/span><span style=\"color: #a9a1e1;\">)<\/span>;\n        <span style=\"color: #98be65;\">}<\/span>\n        <span style=\"color: #51afef;\">for<\/span> <span style=\"color: #dcaeea;\">edge<\/span> <span style=\"color: #51afef;\">in<\/span> &amp; <span style=\"color: #51afef;\">self<\/span>.edges<span style=\"color: #98be65;\">{<\/span>\n            graph.push<span style=\"color: #a9a1e1;\">(<\/span>edge.to_string<span style=\"color: #51afef;\">()<\/span><span style=\"color: #a9a1e1;\">)<\/span>;\n        <span style=\"color: #98be65;\">}<\/span>\n        <span style=\"color: #51afef;\">for<\/span> <span style=\"color: #dcaeea;\">rank<\/span> <span style=\"color: #51afef;\">in<\/span> &amp; <span style=\"color: #51afef;\">self<\/span>.ranks<span style=\"color: #98be65;\">{<\/span>\n            graph.push<span style=\"color: #a9a1e1;\">(<\/span>rank.to_string<span style=\"color: #51afef;\">()<\/span><span style=\"color: #a9a1e1;\">)<\/span>;\n        <span style=\"color: #98be65;\">}<\/span>\n        graph.push<span style=\"color: #98be65;\">(<\/span><span style=\"color: #98be65;\">\"}\"<\/span>.into<span style=\"color: #a9a1e1;\">()<\/span><span style=\"color: #98be65;\">)<\/span>;\n        graph.push<span style=\"color: #98be65;\">(<\/span><span style=\"color: #98be65;\">\"}\"<\/span>.into<span style=\"color: #a9a1e1;\">()<\/span><span style=\"color: #98be65;\">)<\/span>;\n        <span style=\"color: #c678dd;\">write!<\/span><span style=\"color: #98be65;\">(<\/span>f,<span style=\"color: #98be65;\">\"<\/span><span style=\"color: #98be65; font-style: italic;\">{}<\/span><span style=\"color: #98be65;\">\"<\/span>,graph.join<span style=\"color: #a9a1e1;\">(<\/span><span style=\"color: #98be65;\">\"\\n\"<\/span><span style=\"color: #a9a1e1;\">)<\/span><span style=\"color: #98be65;\">)<\/span>\n    <span style=\"color: #c678dd;\">}<\/span>\n<span style=\"color: #51afef;\">}<\/span>\n<\/pre>\n<\/div>\n\n<p> We are now finally able to generate the graph we saw at the beginning of the article <\/p>\n\n<div class=\"org-src-container\">\n<label class=\"org-src-name\"><em><\/em><\/label>\n<pre class=\"src src-dot\" id=\"nil\">digraph {\nrankdir = BT;\nsubgraph{\nnode1 [label=\"petal_length &gt; 2.45e0\", shape=\"box\"];\nnode3 [label=\"Setosa 1\", shape=\"box\", style=\"rounded,filled\", fillcolor=\"green\"];\nnode2 [label=\"petal_width &gt; 1.75e0\", shape=\"box\"];\nnode5 [label=\"petal_length &gt; 4.95e0\", shape=\"box\"];\nnode11 [label=\"petal_width &gt; 1.65e0\", shape=\"box\"];\nnode23 [label=\"Versicolor 1\", shape=\"box\", style=\"rounded,filled\", fillcolor=\"green\"];\nnode22 [label=\"Virginica 1\", shape=\"box\", style=\"rounded,filled\", fillcolor=\"green\"];\nnode10 [label=\"petal_width &gt; 1.55e0\", shape=\"box\"];\nnode21 [label=\"Virginica 1\", shape=\"box\", style=\"rounded,filled\", fillcolor=\"green\"];\nnode20 [label=\"sepal_length &gt; 6.95e0\", shape=\"box\"];\nnode41 [label=\"Versicolor 1\", shape=\"box\", style=\"rounded,filled\", fillcolor=\"green\"];\nnode40 [label=\"Virginica 1\", shape=\"box\", style=\"rounded,filled\", fillcolor=\"green\"];\nnode4 [label=\"petal_length &gt; 4.85e0\", shape=\"box\"];\nnode9 [label=\"sepal_length &gt; 5.95e0\", shape=\"box\"];\nnode19 [label=\"Versicolor 1\", shape=\"box\", style=\"rounded,filled\", fillcolor=\"green\"];\nnode18 [label=\"Virginica 1\", shape=\"box\", style=\"rounded,filled\", fillcolor=\"green\"];\nnode8 [label=\"Virginica 1\", shape=\"box\", style=\"rounded,filled\", fillcolor=\"green\"];\nnode1 -&gt; node3 [label=\"no\"]\nnode1 -&gt; node2 [label=\"yes\"]\nnode2 -&gt; node5 [label=\"no\"]\nnode5 -&gt; node11 [label=\"no\"]\nnode11 -&gt; node23 [label=\"no\"]\nnode11 -&gt; node22 [label=\"yes\"]\nnode5 -&gt; node10 [label=\"yes\"]\nnode10 -&gt; node21 [label=\"no\"]\nnode10 -&gt; node20 [label=\"yes\"]\nnode20 -&gt; node41 [label=\"no\"]\nnode20 -&gt; node40 [label=\"yes\"]\nnode2 -&gt; node4 [label=\"yes\"]\nnode4 -&gt; node9 [label=\"no\"]\nnode9 -&gt; node19 [label=\"no\"]\nnode9 -&gt; node18 [label=\"yes\"]\nnode4 -&gt; node8 [label=\"yes\"]\n{rank = same; node1;}\n{rank = same; node3; node2;}\n{rank = same; node5; node4;}\n{rank = same; node11; node10; node9; node8;}\n{rank = same; node23; node22; node21; node20; node19; node18;}\n{rank = same; node41; node40;}\n}\n}\n\n<\/pre>\n<\/div>\n\n<div id=\"org87bf74f\" class=\"figure\"> <p><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_tree_result.png?ssl=1\" alt=\"post017_tree_result.png\" \/> <\/p> <\/div>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"outline-container-org777acb0\" class=\"outline-2\">\n<h2 id=\"org777acb0\">Some effects of tree creation options<\/h2>\n<div class=\"outline-text-2\" id=\"text-org777acb0\">\n<p> Here I show the effect of a couple of options <\/p>\n\n<ul class=\"org-ul\">\n<li>not reusing features (quite uncommon for this kind of tree)<\/li>\n<li>limiting tree depth<\/li>\n<\/ul>\n<\/div>\n<div id=\"outline-container-orgd275090\" class=\"outline-3\">\n<h3 id=\"orgd275090\">Not reusing features<\/h3>\n<div class=\"outline-text-3\" id=\"text-orgd275090\">\n<p> This is typically used when using categorical features. A popular approach is to transform these feature using one-hot encoding, so each column contains only a boolean value. In this case it does not make sense to find more than one split value. <\/p>\n\n<div id=\"org51faf50\" class=\"figure\"> <p><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_tree_no_reuse.png?ssl=1\" alt=\"post017_tree_no_reuse.png\" \/> <\/p> <\/div>\n<\/div>\n<\/div>\n<div id=\"outline-container-org535e008\" class=\"outline-3\">\n<h3 id=\"org535e008\">Limiting tree depth<\/h3>\n<div class=\"outline-text-3\" id=\"text-org535e008\">\n<p> In this case we allow each branch to keep splitting until a fixed limit. <\/p>\n\n<p> More sophisticated approaches are possible like to to prune each branch dynamically. <\/p>\n\n<div id=\"orga5bb728\" class=\"figure\"> <p><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_tree_limited.png?ssl=1\" alt=\"post017_tree_limited.png\" \/> <\/p> <\/div>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"outline-container-orgffeb136\" class=\"outline-2\">\n<h2 id=\"orgffeb136\">Conclusions?<\/h2>\n<div class=\"outline-text-2\" id=\"text-orgffeb136\">\n<p> We still need to evaluate the performance of our tree using our data and other implementations too. <\/p>\n\n<p> In order to complete this step we need an effective way to <\/p>\n\n<ul class=\"org-ul\">\n<li>create predictions from some unknown data<\/li>\n<li>cross validate hyperparameters tuning<\/li>\n<\/ul>\n\n<p> But these are subject for another post <\/p>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"Completing the creation of a classification decision tree in Rust","protected":false},"author":1,"featured_media":484,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","inline_featured_image":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[27],"tags":[5],"class_list":["post-487","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-machine-learning","tag-rust"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Growing a (Decision) Tree - Noise On The Net<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Growing a (Decision) Tree - Noise On The Net\" \/>\n<meta property=\"og:description\" content=\"Completing the creation of a classification decision tree in Rust\" \/>\n<meta property=\"og:url\" content=\"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/\" \/>\n<meta property=\"og:site_name\" content=\"Noise On The Net\" \/>\n<meta property=\"article:published_time\" content=\"2024-06-09T13:45:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-09T14:09:11+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_full_tree_result.png?fit=951%2C682&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"951\" \/>\n\t<meta property=\"og:image:height\" content=\"682\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"marco.p.v.vezzoli\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"marco.p.v.vezzoli\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/\"},\"author\":{\"name\":\"marco.p.v.vezzoli\",\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/#\\\/schema\\\/person\\\/88c3a70f2b23480197bc61d6e1e2e982\"},\"headline\":\"Growing a (Decision) Tree\",\"datePublished\":\"2024-06-09T13:45:00+00:00\",\"dateModified\":\"2024-06-09T14:09:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/\"},\"wordCount\":1105,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/#\\\/schema\\\/person\\\/88c3a70f2b23480197bc61d6e1e2e982\"},\"image\":{\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/noiseonthenet.space\\\/noise\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/post017_full_tree_result.png?fit=951%2C682&ssl=1\",\"keywords\":[\"Rust\"],\"articleSection\":[\"Machine learning\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/\",\"url\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/\",\"name\":\"Growing a (Decision) Tree - Noise On The Net\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/noiseonthenet.space\\\/noise\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/post017_full_tree_result.png?fit=951%2C682&ssl=1\",\"datePublished\":\"2024-06-09T13:45:00+00:00\",\"dateModified\":\"2024-06-09T14:09:11+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/noiseonthenet.space\\\/noise\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/post017_full_tree_result.png?fit=951%2C682&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/noiseonthenet.space\\\/noise\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/post017_full_tree_result.png?fit=951%2C682&ssl=1\",\"width\":951,\"height\":682},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/2024\\\/06\\\/growing-a-decision-tree\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Growing a (Decision) Tree\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/#website\",\"url\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/\",\"name\":\"Noise On The Net\",\"description\":\"Sharing adventures in code\",\"publisher\":{\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/#\\\/schema\\\/person\\\/88c3a70f2b23480197bc61d6e1e2e982\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/#\\\/schema\\\/person\\\/88c3a70f2b23480197bc61d6e1e2e982\",\"name\":\"marco.p.v.vezzoli\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b9d9aab1df560bc14d73b0b442198f196ce39e7c7a38df1dc22fec0b97f17da9?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b9d9aab1df560bc14d73b0b442198f196ce39e7c7a38df1dc22fec0b97f17da9?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b9d9aab1df560bc14d73b0b442198f196ce39e7c7a38df1dc22fec0b97f17da9?s=96&d=mm&r=g\",\"caption\":\"marco.p.v.vezzoli\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b9d9aab1df560bc14d73b0b442198f196ce39e7c7a38df1dc22fec0b97f17da9?s=96&d=mm&r=g\"},\"description\":\"Self taught assembler programming at 11 on my C64 (1983). Never stopped since then -- always looking up for curious things in the software development, data science and AI. Linux and FOSS user since 1994. MSc in physics in 1996. Working in large semiconductor companies since 1997 (STM, Micron) developing analytics and full stack web infrastructures, microservices, ML solutions\",\"sameAs\":[\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/marco-paolo-valerio-vezzoli-0663835\\\/\"],\"url\":\"https:\\\/\\\/noiseonthenet.space\\\/noise\\\/author\\\/marco-p-v-vezzoli\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Growing a (Decision) Tree - Noise On The Net","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/","og_locale":"en_US","og_type":"article","og_title":"Growing a (Decision) Tree - Noise On The Net","og_description":"Completing the creation of a classification decision tree in Rust","og_url":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/","og_site_name":"Noise On The Net","article_published_time":"2024-06-09T13:45:00+00:00","article_modified_time":"2024-06-09T14:09:11+00:00","og_image":[{"width":951,"height":682,"url":"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_full_tree_result.png?fit=951%2C682&ssl=1","type":"image\/png"}],"author":"marco.p.v.vezzoli","twitter_card":"summary_large_image","twitter_misc":{"Written by":"marco.p.v.vezzoli","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/#article","isPartOf":{"@id":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/"},"author":{"name":"marco.p.v.vezzoli","@id":"https:\/\/noiseonthenet.space\/noise\/#\/schema\/person\/88c3a70f2b23480197bc61d6e1e2e982"},"headline":"Growing a (Decision) Tree","datePublished":"2024-06-09T13:45:00+00:00","dateModified":"2024-06-09T14:09:11+00:00","mainEntityOfPage":{"@id":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/"},"wordCount":1105,"commentCount":0,"publisher":{"@id":"https:\/\/noiseonthenet.space\/noise\/#\/schema\/person\/88c3a70f2b23480197bc61d6e1e2e982"},"image":{"@id":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_full_tree_result.png?fit=951%2C682&ssl=1","keywords":["Rust"],"articleSection":["Machine learning"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/","url":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/","name":"Growing a (Decision) Tree - Noise On The Net","isPartOf":{"@id":"https:\/\/noiseonthenet.space\/noise\/#website"},"primaryImageOfPage":{"@id":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/#primaryimage"},"image":{"@id":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_full_tree_result.png?fit=951%2C682&ssl=1","datePublished":"2024-06-09T13:45:00+00:00","dateModified":"2024-06-09T14:09:11+00:00","breadcrumb":{"@id":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/#primaryimage","url":"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_full_tree_result.png?fit=951%2C682&ssl=1","contentUrl":"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_full_tree_result.png?fit=951%2C682&ssl=1","width":951,"height":682},{"@type":"BreadcrumbList","@id":"https:\/\/noiseonthenet.space\/noise\/2024\/06\/growing-a-decision-tree\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/noiseonthenet.space\/noise\/"},{"@type":"ListItem","position":2,"name":"Growing a (Decision) Tree"}]},{"@type":"WebSite","@id":"https:\/\/noiseonthenet.space\/noise\/#website","url":"https:\/\/noiseonthenet.space\/noise\/","name":"Noise On The Net","description":"Sharing adventures in code","publisher":{"@id":"https:\/\/noiseonthenet.space\/noise\/#\/schema\/person\/88c3a70f2b23480197bc61d6e1e2e982"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/noiseonthenet.space\/noise\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/noiseonthenet.space\/noise\/#\/schema\/person\/88c3a70f2b23480197bc61d6e1e2e982","name":"marco.p.v.vezzoli","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/b9d9aab1df560bc14d73b0b442198f196ce39e7c7a38df1dc22fec0b97f17da9?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/b9d9aab1df560bc14d73b0b442198f196ce39e7c7a38df1dc22fec0b97f17da9?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b9d9aab1df560bc14d73b0b442198f196ce39e7c7a38df1dc22fec0b97f17da9?s=96&d=mm&r=g","caption":"marco.p.v.vezzoli"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/b9d9aab1df560bc14d73b0b442198f196ce39e7c7a38df1dc22fec0b97f17da9?s=96&d=mm&r=g"},"description":"Self taught assembler programming at 11 on my C64 (1983). Never stopped since then -- always looking up for curious things in the software development, data science and AI. Linux and FOSS user since 1994. MSc in physics in 1996. Working in large semiconductor companies since 1997 (STM, Micron) developing analytics and full stack web infrastructures, microservices, ML solutions","sameAs":["https:\/\/noiseonthenet.space\/noise\/","https:\/\/www.linkedin.com\/in\/marco-paolo-valerio-vezzoli-0663835\/"],"url":"https:\/\/noiseonthenet.space\/noise\/author\/marco-p-v-vezzoli\/"}]}},"jetpack_featured_media_url":"https:\/\/i0.wp.com\/noiseonthenet.space\/noise\/wp-content\/uploads\/2024\/06\/post017_full_tree_result.png?fit=951%2C682&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pdDUZ5-7R","jetpack-related-posts":[],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/posts\/487","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/comments?post=487"}],"version-history":[{"count":5,"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/posts\/487\/revisions"}],"predecessor-version":[{"id":506,"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/posts\/487\/revisions\/506"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/media\/484"}],"wp:attachment":[{"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/media?parent=487"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/categories?post=487"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/noiseonthenet.space\/noise\/wp-json\/wp\/v2\/tags?post=487"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}