Skip to content

Commit 6ff7b04

Browse files
committed
Version 1.0.1
1 parent 732dd36 commit 6ff7b04

31 files changed

+273
-332
lines changed

.github/workflows/test.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ jobs:
1111
test:
1212
runs-on: ubuntu-latest
1313
steps:
14-
- uses: actions/checkout@v2.0.0
15-
- uses: erlef/setup-beam@v1.9.0
14+
- uses: actions/checkout@v4
15+
- uses: erlef/setup-beam@v1
1616
with:
17-
otp-version: "23.2"
18-
gleam-version: "0.22.1"
19-
- run: gleam format --check src test
17+
otp-version: "27.0.0"
18+
gleam-version: "1.5.1"
19+
rebar3-version: "3"
2020
- run: gleam deps download
2121
- run: gleam test
22+
- run: gleam format --check src test

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Turn data into functions! A simple and functional **machine learning** library,
88

99
```erlang
1010
{deps, [
11-
{emel, "1.0.0"}
11+
{emel, "1.0.1"}
1212
]}.
1313
```
1414

@@ -17,7 +17,7 @@ Turn data into functions! A simple and functional **machine learning** library,
1717
```elixir
1818
defp deps do
1919
[
20-
{:emel, "~> 1.0.0"}
20+
{:emel, "~> 1.0.1"}
2121
]
2222
end
2323
```

gleam.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name = "emel"
2-
version = "1.0.0"
2+
version = "1.0.1"
33
licences = ["Apache-2.0"]
44
description = "Turn data into functions in the Erlang ecosystem"
55

@@ -14,10 +14,10 @@ user = "mrdimosthenis"
1414
repo = "emel"
1515

1616
[dependencies]
17-
gleam_stdlib = "~> 0.22"
18-
minigen = "~> 0.0"
19-
gleam_zlists = "~> 0.0"
20-
gleam_synapses = "~> 1.0"
17+
gleam_stdlib = "~> 0.40.0"
18+
minigen = "~> 0.1.1"
19+
gleam_zlists = "~> 1.0.0"
20+
gleam_synapses = "~> 1.0.1"
2121

2222
[dev-dependencies]
23-
gleeunit = "~> 0.6"
23+
gleeunit = "~> 1.2.0"

manifest.toml

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,18 @@
22
# You typically do not need to edit this file
33

44
packages = [
5-
{ name = "gleam_json", version = "0.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "E42443C98AA66E30143C24818F2CEA801491C10CE6B1A5EDDF3FC4ABDC7601CB" },
6-
{ name = "gleam_stdlib", version = "0.22.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "9C6C66EDAAFD097267089565488DEDFC111A0497DE9CB2C42248E26330CC48E9" },
7-
{ name = "gleam_synapses", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "minigen", "gleam_stdlib", "gleam_zlists"], otp_app = "gleam_synapses", source = "hex", outer_checksum = "B8D86A43EADC88D951AC9B3E40F667AFCDB30BA13485123E503041FBA542DE04" },
8-
{ name = "gleam_zlists", version = "0.0.4", build_tools = ["gleam"], requirements = ["gleam_stdlib", "zlists"], otp_app = "gleam_zlists", source = "hex", outer_checksum = "A71998C938A90475051845960ABD73647DB9734088E78A58B0CDFC41B1486461" },
9-
{ name = "gleeunit", version = "0.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "5BF486C3E135B7F5ED8C054925FC48E5B2C79016A39F416FD8CF2E860520EE55" },
10-
{ name = "minigen", version = "0.0.3", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "minigen", source = "hex", outer_checksum = "F74D7B2BF5E05A493BF2048BB557F8FC08AA93EB5A6664FC66FD5A69C3A57B6A" },
11-
{ name = "thoas", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "B8E1F8C8FAD317C0B75239A9234CB093DE1FB8BE7BA3E41433FF80A0B3353973" },
5+
{ name = "gleam_json", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "CB10B0E7BF44282FB25162F1A24C1A025F6B93E777CCF238C4017E4EEF2CDE97" },
6+
{ name = "gleam_stdlib", version = "0.40.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "86606B75A600BBD05E539EB59FABC6E307EEEA7B1E5865AFB6D980A93BCB2181" },
7+
{ name = "gleam_synapses", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib", "gleam_zlists", "minigen"], otp_app = "gleam_synapses", source = "hex", outer_checksum = "2097F516EF2131B6FCE3D2058C787632D7BFDEE3B91AFD3CBF669D43CE722BCE" },
8+
{ name = "gleam_zlists", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "zlists"], otp_app = "gleam_zlists", source = "hex", outer_checksum = "DCA7EAAAB38C0BB3A16E7490EFF51DA0C2355A63B60BC3DD98752FDE96314B94" },
9+
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
10+
{ name = "minigen", version = "0.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "minigen", source = "hex", outer_checksum = "AFD1E637A7F429C2C57438FB635CCCAD818AA9C39D6F6E1A5200E5952940E2FD" },
1211
{ name = "zlists", version = "0.0.4", build_tools = ["mix", "rebar3"], requirements = [], otp_app = "zlists", source = "hex", outer_checksum = "BABC8B78984E4988DAFEB9E07A77F04D3F8EA208D49E60B6669DA43B0D2C2C4B" },
1312
]
1413

1514
[requirements]
16-
gleam_stdlib = "~> 0.22"
17-
gleam_synapses = "~> 1.0"
18-
gleam_zlists = "~> 0.0"
19-
gleeunit = "~> 0.6"
20-
minigen = "~> 0.0"
15+
gleam_stdlib = { version = "~> 0.40.0" }
16+
gleam_synapses = { version = "~> 1.0.1" }
17+
gleam_zlists = { version = "~> 1.0.0" }
18+
gleeunit = { version = "~> 1.2.0" }
19+
minigen = { version = "~> 0.1.1" }

src/emel/lazy/math/algebra.gleam

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import emel/utils/zlist as ut_zlist
33
import gleam/float
44
import gleam/int
55
import gleam/order.{Eq}
6-
import gleam_zlists.{ZList} as zlist
6+
import gleam_zlists.{type ZList} as zlist
77

88
pub fn first_minor(
99
matrix: ZList(ZList(Float)),
@@ -19,7 +19,7 @@ pub fn determinant(matrix: ZList(ZList(Float))) -> Float {
1919
case zlist.count(matrix) {
2020
0 -> 1.0
2121
2 -> {
22-
let [[a, b], [c, d]] = ut_zlist.to_list_of_lists(matrix)
22+
let assert [[a, b], [c, d]] = ut_zlist.to_list_of_lists(matrix)
2323
a *. d -. c *. b
2424
}
2525
_ ->

src/emel/lazy/math/geometry.gleam

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import emel/utils/result as ut_res
22
import emel/utils/zlist as ut_zlist
33
import gleam/float
4-
import gleam/function
5-
import gleam_zlists.{ZList} as zlist
4+
import gleam_zlists.{type ZList} as zlist
65

76
pub fn dot_product(x: ZList(Float), y: ZList(Float)) -> Float {
87
zlist.zip(x, y)
@@ -27,7 +26,7 @@ pub fn euclidean_distance(x: ZList(Float), y: ZList(Float)) -> Float {
2726

2827
pub fn magnitude(vector: ZList(Float)) -> Float {
2928
vector
30-
|> zlist.map(function.constant(0.0))
29+
|> zlist.map(fn(_) { 0.0 })
3130
|> euclidean_distance(vector)
3231
}
3332

@@ -46,20 +45,16 @@ pub fn centroid(points: ZList(ZList(Float))) -> ZList(Float) {
4645
|> zlist.uncons
4746
|> ut_res.unsafe_res
4847
let #(s, n) =
49-
zlist.reduce(
50-
tl,
51-
#(hd, 1.0),
52-
fn(v, acc) {
53-
let #(acc_s, acc_n) = acc
54-
let next_acc_s =
55-
zlist.zip(acc_s, v)
56-
|> zlist.map(fn(t) {
57-
let #(si, vi) = t
58-
si +. vi
59-
})
60-
let next_acc_n = acc_n +. 1.0
61-
#(next_acc_s, next_acc_n)
62-
},
63-
)
48+
zlist.reduce(tl, #(hd, 1.0), fn(v, acc) {
49+
let #(acc_s, acc_n) = acc
50+
let next_acc_s =
51+
zlist.zip(acc_s, v)
52+
|> zlist.map(fn(t) {
53+
let #(si, vi) = t
54+
si +. vi
55+
})
56+
let next_acc_n = acc_n +. 1.0
57+
#(next_acc_s, next_acc_n)
58+
})
6459
zlist.map(s, fn(x) { x /. n })
6560
}
Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import gleam/float
22
import gleam/int
3-
import gleam_zlists.{ZList} as zlist
3+
import gleam_zlists.{type ZList} as zlist
44

5-
external fn log(Float) -> Float =
6-
"math" "log"
5+
@external(erlang, "math", "log")
6+
pub fn log(x: Float) -> Float
77

88
fn log_base(x: Float, b: Float) -> Float {
99
log(x) /. log(b)
@@ -21,19 +21,15 @@ pub fn entropy(probability_values: ZList(Float)) -> Float {
2121

2222
pub fn classical_probability(observations: ZList(a), event: a) -> Float {
2323
let #(numerator, denominator) =
24-
zlist.reduce(
25-
observations,
26-
#(0.0, 0.0),
27-
fn(ev, acc) {
28-
let #(numer, denom) = acc
29-
let next_numer = case ev == event {
30-
True -> numer +. 1.0
31-
False -> numer
32-
}
33-
let next_denom = denom +. 1.0
34-
#(next_numer, next_denom)
35-
},
36-
)
24+
zlist.reduce(observations, #(0.0, 0.0), fn(ev, acc) {
25+
let #(numer, denom) = acc
26+
let next_numer = case ev == event {
27+
True -> numer +. 1.0
28+
False -> numer
29+
}
30+
let next_denom = denom +. 1.0
31+
#(next_numer, next_denom)
32+
})
3733
numerator /. denominator
3834
}
3935

@@ -42,16 +38,12 @@ pub fn mean_absolute_error(
4238
observations: ZList(Float),
4339
) -> Float {
4440
let #(numerator, denominator) =
45-
zlist.reduce(
46-
zlist.zip(predictions, observations),
47-
#(0.0, 0.0),
48-
fn(p, acc) {
49-
let #(v1, v2) = p
50-
let #(numer, denom) = acc
51-
let next_numer = numer +. float.absolute_value(v1 -. v2)
52-
let next_denom = denom +. 1.0
53-
#(next_numer, next_denom)
54-
},
55-
)
41+
zlist.reduce(zlist.zip(predictions, observations), #(0.0, 0.0), fn(p, acc) {
42+
let #(v1, v2) = p
43+
let #(numer, denom) = acc
44+
let next_numer = numer +. float.absolute_value(v1 -. v2)
45+
let next_denom = denom +. 1.0
46+
#(next_numer, next_denom)
47+
})
5648
numerator /. denominator
5749
}

src/emel/lazy/ml/decision_tree.gleam

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import emel/lazy/math/statistics as stats
22
import emel/utils/result as ut_res
33
import emel/utils/zlist as ut_zlist
4+
import gleam/dict.{type Dict}
45
import gleam/int
5-
import gleam/map.{Map}
66
import gleam/pair
7-
import gleam_zlists.{ZList} as zlist
7+
import gleam_zlists.{type ZList} as zlist
88

99
pub fn entropy_with_size(
10-
dataset: ZList(Map(String, String)),
10+
dataset: ZList(Dict(String, String)),
1111
class_attr: String,
1212
) -> #(Float, Int) {
1313
let #(freqs, size) =
@@ -23,7 +23,7 @@ pub fn entropy_with_size(
2323
}
2424

2525
pub fn feature_entropy(
26-
dataset: ZList(Map(String, String)),
26+
dataset: ZList(Dict(String, String)),
2727
class_attr: String,
2828
feature: String,
2929
dataset_size: Int,
@@ -40,23 +40,23 @@ pub fn feature_entropy(
4040
}
4141

4242
fn same_class(
43-
rule: Map(String, String),
43+
rule: Dict(String, String),
4444
class_attr: String,
45-
sub_dataset: ZList(Map(String, String)),
46-
) -> ZList(Map(String, String)) {
45+
sub_dataset: ZList(Dict(String, String)),
46+
) -> ZList(Dict(String, String)) {
4747
sub_dataset
4848
|> zlist.head
4949
|> ut_res.unsafe_res
5050
|> ut_res.unsafe_get(class_attr)
51-
|> map.insert(rule, class_attr, _)
51+
|> dict.insert(rule, class_attr, _)
5252
|> zlist.singleton
5353
}
5454

5555
fn exhausted_attributes(
56-
rule: Map(String, String),
56+
rule: Dict(String, String),
5757
class_attr: String,
58-
grouped_by_class: ZList(#(String, ZList(Map(String, String)))),
59-
) -> ZList(Map(String, String)) {
58+
grouped_by_class: ZList(#(String, ZList(Dict(String, String)))),
59+
) -> ZList(Dict(String, String)) {
6060
grouped_by_class
6161
|> ut_zlist.max_by(fn(t) {
6262
t
@@ -66,16 +66,16 @@ fn exhausted_attributes(
6666
})
6767
|> ut_res.unsafe_res
6868
|> pair.first
69-
|> map.insert(rule, class_attr, _)
69+
|> dict.insert(rule, class_attr, _)
7070
|> zlist.singleton
7171
}
7272

7373
fn unfold_rule(
74-
rule: Map(String, String),
74+
rule: Dict(String, String),
7575
non_selected_attrs: ZList(String),
7676
class_attr: String,
77-
sub_dataset: ZList(Map(String, String)),
78-
) -> ZList(Map(String, String)) {
77+
sub_dataset: ZList(Dict(String, String)),
78+
) -> ZList(Dict(String, String)) {
7979
let grouped_by_class =
8080
ut_zlist.group_by(sub_dataset, ut_res.unsafe_get(_, class_attr))
8181
case zlist.count(grouped_by_class) {
@@ -89,24 +89,19 @@ fn unfold_rule(
8989
let next_selected_attr =
9090
non_selected_attrs
9191
|> ut_zlist.max_by(fn(feature) {
92-
entropy -. feature_entropy(
93-
sub_dataset,
94-
class_attr,
95-
feature,
96-
dataset_size,
97-
)
92+
entropy
93+
-. feature_entropy(sub_dataset, class_attr, feature, dataset_size)
9894
})
9995
|> ut_res.unsafe_res
10096
let next_non_selected_attrs =
101-
zlist.filter(
102-
non_selected_attrs,
103-
fn(attr) { attr != next_selected_attr },
104-
)
97+
zlist.filter(non_selected_attrs, fn(attr) {
98+
attr != next_selected_attr
99+
})
105100
sub_dataset
106101
|> ut_zlist.group_by(ut_res.unsafe_get(_, next_selected_attr))
107102
|> zlist.flat_map(fn(t) {
108103
let #(feature_val, sub_group) = t
109-
let next_rule = map.insert(rule, next_selected_attr, feature_val)
104+
let next_rule = dict.insert(rule, next_selected_attr, feature_val)
110105
unfold_rule(
111106
next_rule,
112107
next_non_selected_attrs,
@@ -120,32 +115,29 @@ fn unfold_rule(
120115
}
121116

122117
pub fn decision_tree(
123-
dataset: ZList(Map(String, String)),
118+
dataset: ZList(Dict(String, String)),
124119
attributes: ZList(String),
125120
class: String,
126-
) -> ZList(Map(String, String)) {
127-
unfold_rule(map.new(), attributes, class, dataset)
121+
) -> ZList(Dict(String, String)) {
122+
unfold_rule(dict.new(), attributes, class, dataset)
128123
}
129124

130125
pub fn classifier(
131-
dataset: ZList(Map(String, String)),
126+
dataset: ZList(Dict(String, String)),
132127
discrete_attributes: ZList(String),
133128
class: String,
134-
) -> fn(Map(String, String)) -> String {
135-
let all_rules: ZList(Map(String, String)) =
129+
) -> fn(Dict(String, String)) -> String {
130+
let all_rules: ZList(Dict(String, String)) =
136131
decision_tree(dataset, discrete_attributes, class)
137132
fn(item) {
138133
all_rules
139134
|> zlist.find(fn(rule) {
140-
zlist.all(
141-
discrete_attributes,
142-
fn(feature) {
143-
case map.get(rule, feature) {
144-
Error(Nil) -> True
145-
Ok(v) -> v == ut_res.unsafe_get(item, feature)
146-
}
147-
},
148-
)
135+
zlist.all(discrete_attributes, fn(feature) {
136+
case dict.get(rule, feature) {
137+
Error(Nil) -> True
138+
Ok(v) -> v == ut_res.unsafe_get(item, feature)
139+
}
140+
})
149141
})
150142
|> ut_res.unsafe_res
151143
|> ut_res.unsafe_get(class)

src/emel/lazy/ml/k_means.gleam

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
import emel/lazy/math/geometry
12
import emel/utils/result as ut_res
23
import emel/utils/zlist as ut_zlist
3-
import emel/lazy/math/geometry
44
import gleam/pair
5-
import gleam/set.{Set}
6-
import gleam_zlists.{ZList} as zlist
5+
import gleam/set.{type Set}
6+
import gleam_zlists.{type ZList} as zlist
77

88
fn point_groups(
99
points: ZList(ZList(Float)),

0 commit comments

Comments
 (0)