ic/
lib.rs

1pub use iris::{
2    classified::ClassifiedIris, params::IrisParams, species::IrisSpecies,
3    unclassified::UnclassifiedIris, Iris,
4};
5pub mod iris;
6
7pub use paths::*;
8pub mod paths {
9    //! Defines paths used by this app.
10
11    pub const PATH_TO_TRAINING_IRISES: &str = "./data/training_irises.csv";
12    pub const PATH_TO_TESTING_IRISES: &str = "./data/testing_irises.csv";
13}
14
15pub mod read;
16pub mod util;
17
18pub use app::{
19    args::AppArgs,
20    cfg::{app_cfg, AppCfg, APP_CFG},
21};
22pub mod app;
23
24use itertools::Itertools;
25
26#[macro_export]
27macro_rules! executable_desc{
28    () => {
29        "App for classifying irises into one of 3 species {Setosa, Versicolor, Virginica}.\n\
30        \n\
31        After running this app, it will:\n\
32        1. Perform an accuracy measure for the testing iris data file dwelling in the ./data folder. \
33            This can be disabled by app argument. \
34            Measure will be rendered to stderr.\n\
35        2. Read all irises from stdin untill EOF. Then classify them. \
36            This will be displayed in stdout.\
37        \n\
38        EXAMPLE usages for app is installed as `iris_classifier`:\n\
39        * `echo '1.,2,3,4' | iris_classifier`\n\
40        * `cat ./data/unclassified_irises.csv | iris_classifier`\n\
41        * `echo 'some.invalid.data' | iris_classifier --separator '.'`\n\
42        * `echo '1 2 3 4' | iris_classifier -s=' '`\n\
43        "
44    }
45}
46
47/// Creates classifier that will map any unclassified iris into classified.
48///
49/// Created classifier will guess classification for iris using KNN algorithm.
50pub fn create_classifier(
51    classified_irises: Vec<ClassifiedIris>,
52    k: usize,
53) -> impl Fn(UnclassifiedIris) -> ClassifiedIris {
54    move |unclassified| {
55        let nearest_classifications = classified_irises
56            .iter()
57            .map(|classified| {
58                util::ComparedByDistSq::new(classified, classified.dist_sq(&unclassified))
59            })
60            .k_smallest(k)
61            .map(|cmpd_by_dist_sq| cmpd_by_dist_sq.val.classification);
62        let mode = util::mode(nearest_classifications).unwrap();
63
64        ClassifiedIris::new(unclassified, mode)
65    }
66}
67
68/// Classifies unclassified irises using classifier.
69pub fn classify_irises<F>(
70    iris_classifier: F,
71    unclassified_irises: Vec<UnclassifiedIris>,
72) -> Vec<ClassifiedIris>
73where
74    F: (Fn(UnclassifiedIris) -> ClassifiedIris) + Send + Sync,
75{
76    use rayon::iter::{IntoParallelIterator, ParallelIterator};
77
78    unclassified_irises
79        .into_par_iter()
80        .map(iris_classifier)
81        .collect()
82}