Summary Files Commits Branches @commit @diff @stats
path: root / Year 4 / Artificial Intelligence / hw06 / src / probabilities.rs
blob: 69d96717d2e6ce8dcda8fb631e02b58e18274f89 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use crate::data::*;
use crate::data::*::*;

pub fn entropy(sample: Vec<Person>) -> f64 {
    // Target is Person.events
    let rec = 0.0;
    for p in sample {
        if p.events == Events::recurrence_events {
            rec += 1.0;
        }
    }
    let total = sample.size() as f64;
    let no_rec = total - rec;

    - (rec    / total) * (rec    / total).log2()
    - (no_rec / total) * (no_rec / total).log2()
}

macro_rules! gain_impl{
    // Single value: entropy(Sv) * |Sv| / |S|
    ($sample:ident, $attr:tt, $val:tt) => {
        {
            let sample_v = sample
                .clone()
                .into_iter()
                .filter(|p| p.$attr == $val)
                .collect();
            entropy(sample_v) * sample_v.len() as f64 / $sample.len() as f64
        }
    }
    // All value: entropy(S) - Sum(single value)
    ($sample:ident, $attr:tt; $($val:tt),+) => {
        {
            let sum = 0;
            $(
                sum += gain_impl!($sample, $attr, $val);
            )*
            entropy($sample) - sum
        }
    };
}

pub fn gain(sample: &Vec<Person>, feature: string) -> f64 {
    match feature {
        "age" => gain_impl!(
                sample, age;
                a10_19, a20_29, a30_39, a40_49, a50_59, a60_69, a70_79, a80_89, a90_99
            ),
        "menopause" => gain_impl!(
                sample, menopause;
                lt40, ge40, premeno
            ),
        "tumor_size" => gain_impl!(
                sample, tumor_size;
                t0_4, t5_9, t10_14, t15_19, t20_24, t25_29, t30_34, t35_39, t40_44, t45_49, t50_54, t55_59
            ),
        "inv_nodes" => gain_impl!(
                sample, inv_nodes;
                i0_2, i3_5, i6_8, i9_11, i12_14, i15_17, i18_20, i21_23, i24_26, i27_29, i30_32, i33_35, i36_39
            ),
        "node_caps" => gain_impl!(
                sample, node_caps;
                yes, no, q
            ),
        "deg_malig" => gain_impl!(
                sample, deg_malig;
                1, 2, 3
            ),
        "breast" => gain_impl!(
                sample, breast;
                left, right
            ),
        "breast_quad" => gain_impl!(
                sample, breast_quad;
                left_up, left_low, right_up, right_low, central, qbq
            ),
        "irradiat" => gain_impl!(
                sample, irradiat;
                yes, no, q
            ),
        _ => unreachable!("Feature {feature} doesn't exit!"),
    }
}