mirror of
https://github.com/sigmasternchen/gleam-community-maths
synced 2025-03-15 07:59:01 +00:00
Merge pull request #17 from NicklasXYZ/main
Fix some typos + add new distance measure
This commit is contained in:
commit
d6549095b4
5 changed files with 171 additions and 49 deletions
|
@ -289,7 +289,7 @@ pub fn proper_divisors(n: Int) -> List(Int) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the sum of the elements in a list:
|
||||
/// Calculate the sum of the elements in a list:
|
||||
///
|
||||
/// \\[
|
||||
/// \sum_{i=1}^n x_i
|
||||
|
@ -337,7 +337,7 @@ pub fn float_sum(arr: List(Float)) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the sum of the elements in a list:
|
||||
/// Calculate the sum of the elements in a list:
|
||||
///
|
||||
/// \\[
|
||||
/// \sum_{i=1}^n x_i
|
||||
|
@ -385,7 +385,7 @@ pub fn int_sum(arr: List(Int)) -> Int {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the product of the elements in a list:
|
||||
/// Calculate the product of the elements in a list:
|
||||
///
|
||||
/// \\[
|
||||
/// \prod_{i=1}^n x_i
|
||||
|
@ -433,7 +433,7 @@ pub fn float_product(arr: List(Float)) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the product of the elements in a list:
|
||||
/// Calculate the product of the elements in a list:
|
||||
///
|
||||
/// \\[
|
||||
/// \prod_{i=1}^n x_i
|
||||
|
@ -481,7 +481,7 @@ pub fn int_product(arr: List(Int)) -> Int {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the cumulative sum of the elements in a list:
|
||||
/// Calculate the cumulative sum of the elements in a list:
|
||||
///
|
||||
/// \\[
|
||||
/// v_j = \sum_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
|
||||
|
@ -530,7 +530,7 @@ pub fn float_cumulative_sum(arr: List(Float)) -> List(Float) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the cumulative sum of the elements in a list:
|
||||
/// Calculate the cumulative sum of the elements in a list:
|
||||
///
|
||||
/// \\[
|
||||
/// v_j = \sum_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
|
||||
|
@ -579,7 +579,7 @@ pub fn int_cumulative_sum(arr: List(Int)) -> List(Int) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the cumulative product of the elements in a list:
|
||||
/// Calculate the cumulative product of the elements in a list:
|
||||
///
|
||||
/// \\[
|
||||
/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
|
||||
|
@ -629,7 +629,7 @@ pub fn float_cumumlative_product(arr: List(Float)) -> List(Float) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the cumulative product of the elements in a list:
|
||||
/// Calculate the cumulative product of the elements in a list:
|
||||
///
|
||||
/// \\[
|
||||
/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
|
||||
|
|
|
@ -28,8 +28,9 @@
|
|||
//// * **Distance measures**
|
||||
//// * [`norm`](#norm)
|
||||
//// * [`manhatten_distance`](#manhatten_distance)
|
||||
//// * [`minkowski_distance`](#minkowski_distance)
|
||||
//// * [`euclidean_distance`](#euclidean_distance)
|
||||
//// * [`chebyshev_distance`](#chebyshev_distance)
|
||||
//// * [`minkowski_distance`](#minkowski_distance)
|
||||
//// * [`cosine_similarity`](#cosine_similarity)
|
||||
//// * **Set & string similarity measures**
|
||||
//// * [`jaccard_index`](#jaccard_index)
|
||||
|
@ -60,7 +61,7 @@ import gleam/int
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the $$p$$-norm of a list (representing a vector):
|
||||
/// Calculate the $$p$$-norm of a list (representing a vector):
|
||||
///
|
||||
/// \\[
|
||||
/// \left( \sum_{i=1}^n \left|x_i\right|^{p} \right)^{\frac{1}{p}}
|
||||
|
@ -120,13 +121,13 @@ pub fn norm(arr: List(Float), p: Float) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the Manhatten distance between two lists (representing vectors):
|
||||
/// Calculate the Manhatten distance between two lists (representing vectors):
|
||||
///
|
||||
/// \\[
|
||||
/// \sum_{i=1}^n \left|x_i - y_i \right|
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i, j$$.
|
||||
/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -139,9 +140,9 @@ pub fn norm(arr: List(Float), p: Float) -> Float {
|
|||
/// pub fn example () {
|
||||
/// let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
||||
///
|
||||
/// // Empty lists returns 0.0
|
||||
/// // Empty lists returns an error
|
||||
/// metrics.manhatten_distance([], [])
|
||||
/// |> should.equal(Ok(0.0))
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Differing lengths returns error
|
||||
/// metrics.manhatten_distance([], [1.0])
|
||||
|
@ -173,13 +174,13 @@ pub fn manhatten_distance(
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the Minkowski distance between two lists (representing vectors):
|
||||
/// Calculate the Minkowski distance between two lists (representing vectors):
|
||||
///
|
||||
/// \\[
|
||||
/// \left( \sum_{i=1}^n \left|x_i - y_i \right|^{p} \right)^{\frac{1}{p}}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$p >= 1$$ is the order, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i, j$$.
|
||||
/// In the formula, $$p >= 1$$ is the order, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i$$.
|
||||
///
|
||||
/// The Minkowski distance is a generalization of both the Euclidean distance ($$p=2$$) and the Manhattan distance ($$p = 1$$).
|
||||
///
|
||||
|
@ -196,7 +197,7 @@ pub fn manhatten_distance(
|
|||
///
|
||||
/// // Empty lists returns 0.0
|
||||
/// metrics.minkowski_distance([], [], 1.0)
|
||||
/// |> should.equal(Ok(0.0))
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Differing lengths returns error
|
||||
/// metrics.minkowski_distance([], [1.0], 1.0)
|
||||
|
@ -224,25 +225,35 @@ pub fn minkowski_distance(
|
|||
yarr: List(Float),
|
||||
p: Float,
|
||||
) -> Result(Float, String) {
|
||||
let xlen: Int = list.length(xarr)
|
||||
let ylen: Int = list.length(yarr)
|
||||
case xlen == ylen {
|
||||
False ->
|
||||
"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."
|
||||
case xarr, yarr {
|
||||
[], _ ->
|
||||
"Invalid input argument: The list xarr is empty."
|
||||
|> Error
|
||||
True ->
|
||||
case p <. 1.0 {
|
||||
True ->
|
||||
"Invalid input argument: p < 1. Valid input is p >= 1."
|
||||
|> Error
|
||||
_, [] ->
|
||||
"Invalid input argument: The list yarr is empty."
|
||||
|> Error
|
||||
_, _ -> {
|
||||
let xlen: Int = list.length(xarr)
|
||||
let ylen: Int = list.length(yarr)
|
||||
case xlen == ylen {
|
||||
False ->
|
||||
list.zip(xarr, yarr)
|
||||
|> list.map(fn(tuple: #(Float, Float)) -> Float {
|
||||
pair.first(tuple) -. pair.second(tuple)
|
||||
})
|
||||
|> norm(p)
|
||||
|> Ok
|
||||
"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."
|
||||
|> Error
|
||||
True ->
|
||||
case p <. 1.0 {
|
||||
True ->
|
||||
"Invalid input argument: p < 1. Valid input is p >= 1."
|
||||
|> Error
|
||||
False ->
|
||||
list.zip(xarr, yarr)
|
||||
|> list.map(fn(tuple: #(Float, Float)) -> Float {
|
||||
pair.first(tuple) -. pair.second(tuple)
|
||||
})
|
||||
|> norm(p)
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,13 +263,13 @@ pub fn minkowski_distance(
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the Euclidean distance between two lists (representing vectors):
|
||||
/// Calculate the Euclidean distance between two lists (representing vectors):
|
||||
///
|
||||
/// \\[
|
||||
/// \left( \sum_{i=1}^n \left|x_i - y_i \right|^{2} \right)^{\frac{1}{2}}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i, j$$.
|
||||
/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -273,7 +284,7 @@ pub fn minkowski_distance(
|
|||
///
|
||||
/// // Empty lists returns 0.0
|
||||
/// metrics.euclidean_distance([], [])
|
||||
/// |> should.equal(Ok(0.0))
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Differing lengths returns error
|
||||
/// metrics.euclidean_distance([], [1.0])
|
||||
|
@ -305,7 +316,82 @@ pub fn euclidean_distance(
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the arithmetic mean of the elements in a list:
|
||||
/// Calculate the Chebyshev distance between two lists (representing vectors):
|
||||
///
|
||||
/// \\[
|
||||
/// \text{max}_{i=1}^n \left|x_i - y_i \right|
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/elementary
|
||||
/// import gleam_community/maths/metrics
|
||||
/// import gleam_community/maths/predicates
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// // Empty lists returns an error
|
||||
/// metrics.chebyshev_distance([], [])
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Differing lengths returns error
|
||||
/// metrics.chebyshev_distance([], [1.0])
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// metrics.chebyshev_distance([-5.0, -10.0, -3.0], [-1.0, -12.0, -3.0])
|
||||
/// |> should.equal(Ok(4.0))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
/// <small>Back to top ↑</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn chebyshev_distance(
|
||||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
) -> Result(Float, String) {
|
||||
case xarr, yarr {
|
||||
[], _ ->
|
||||
"Invalid input argument: The list xarr is empty."
|
||||
|> Error
|
||||
_, [] ->
|
||||
"Invalid input argument: The list yarr is empty."
|
||||
|> Error
|
||||
_, _ -> {
|
||||
let xlen: Int = list.length(xarr)
|
||||
let ylen: Int = list.length(yarr)
|
||||
case xlen == ylen {
|
||||
False ->
|
||||
"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."
|
||||
|> Error
|
||||
True -> {
|
||||
let differences =
|
||||
list.zip(xarr, yarr)
|
||||
|> list.map(fn(tuple: #(Float, Float)) -> Float {
|
||||
{ pair.first(tuple) -. pair.second(tuple) }
|
||||
|> piecewise.float_absolute_value()
|
||||
})
|
||||
differences
|
||||
|> piecewise.list_maximum(float.compare)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculate the arithmetic mean of the elements in a list:
|
||||
///
|
||||
/// \\[
|
||||
/// \bar{x} = \frac{1}{n}\sum_{i=1}^n x_i
|
||||
|
@ -360,7 +446,7 @@ pub fn mean(arr: List(Float)) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the median of the elements in a list.
|
||||
/// Calculate the median of the elements in a list.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -427,7 +513,7 @@ pub fn median(arr: List(Float)) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the sample variance of the elements in a list:
|
||||
/// Calculate the sample variance of the elements in a list:
|
||||
/// \\[
|
||||
/// s^{2} = \frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x})
|
||||
/// \\]
|
||||
|
@ -503,7 +589,7 @@ pub fn variance(arr: List(Float), ddof: Int) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the sample standard deviation of the elements in a list:
|
||||
/// Calculate the sample standard deviation of the elements in a list:
|
||||
/// \\[
|
||||
/// s = \left(\frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x})\right)^{\frac{1}{2}}
|
||||
/// \\]
|
||||
|
@ -858,8 +944,6 @@ pub fn cosine_similarity(
|
|||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
) -> Result(Float, String) {
|
||||
let xlen: Int = list.length(xarr)
|
||||
let ylen: Int = list.length(yarr)
|
||||
case xarr, yarr {
|
||||
[], _ ->
|
||||
"Invalid input argument: The list xarr is empty."
|
||||
|
@ -868,6 +952,8 @@ pub fn cosine_similarity(
|
|||
"Invalid input argument: The list yarr is empty."
|
||||
|> Error
|
||||
_, _ -> {
|
||||
let xlen: Int = list.length(xarr)
|
||||
let ylen: Int = list.length(yarr)
|
||||
case xlen == ylen {
|
||||
False ->
|
||||
"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
//// * [`is_perfect`](#is_perfect)
|
||||
//// * [`is_even`](#is_even)
|
||||
//// * [`is_odd`](#is_odd)
|
||||
//// * [`is_prime`](#is_prime)
|
||||
|
||||
import gleam/pair
|
||||
import gleam/int
|
||||
|
|
|
@ -53,9 +53,9 @@ pub fn float_list_norm_test() {
|
|||
pub fn float_list_manhatten_test() {
|
||||
let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
||||
|
||||
// Empty lists returns 0.0
|
||||
// Empty lists returns an error
|
||||
metrics.manhatten_distance([], [])
|
||||
|> should.equal(Ok(0.0))
|
||||
|> should.be_error()
|
||||
|
||||
// Differing lengths returns error
|
||||
metrics.manhatten_distance([], [1.0])
|
||||
|
@ -85,9 +85,9 @@ pub fn float_list_manhatten_test() {
|
|||
pub fn float_list_minkowski_test() {
|
||||
let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
||||
|
||||
// Empty lists returns 0.0
|
||||
// Empty lists returns an error
|
||||
metrics.minkowski_distance([], [], 1.0)
|
||||
|> should.equal(Ok(0.0))
|
||||
|> should.be_error()
|
||||
|
||||
// Differing lengths returns error
|
||||
metrics.minkowski_distance([], [1.0], 1.0)
|
||||
|
@ -141,9 +141,9 @@ pub fn float_list_minkowski_test() {
|
|||
pub fn float_list_euclidean_test() {
|
||||
let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
||||
|
||||
// Empty lists returns 0.0
|
||||
// Empty lists returns an error
|
||||
metrics.euclidean_distance([], [])
|
||||
|> should.equal(Ok(0.0))
|
||||
|> should.be_error()
|
||||
|
||||
// Differing lengths returns error
|
||||
metrics.euclidean_distance([], [1.0])
|
||||
|
@ -291,7 +291,7 @@ pub fn example_cosine_similarity_test() {
|
|||
metrics.cosine_similarity([], [1.0, 2.0, 3.0])
|
||||
|> should.be_error()
|
||||
|
||||
// Differen sized lists returns an error
|
||||
// Different sized lists returns an error
|
||||
metrics.cosine_similarity([1.0, 2.0], [1.0, 2.0, 3.0, 4.0])
|
||||
|> should.be_error()
|
||||
|
||||
|
@ -307,3 +307,34 @@ pub fn example_cosine_similarity_test() {
|
|||
metrics.cosine_similarity([-1.0, -2.0, -3.0], [1.0, 2.0, 3.0])
|
||||
|> should.equal(Ok(-1.0))
|
||||
}
|
||||
|
||||
pub fn example_chebyshev_distance() {
|
||||
// Empty lists returns an error
|
||||
metrics.chebyshev_distance([], [])
|
||||
|> should.be_error()
|
||||
|
||||
// One empty list returns an error
|
||||
metrics.chebyshev_distance([1.0, 2.0, 3.0], [])
|
||||
|> should.be_error()
|
||||
|
||||
// One empty list returns an error
|
||||
metrics.chebyshev_distance([], [1.0, 2.0, 3.0])
|
||||
|> should.be_error()
|
||||
|
||||
// Different sized lists returns an error
|
||||
metrics.chebyshev_distance([1.0, 2.0], [1.0, 2.0, 3.0, 4.0])
|
||||
|> should.be_error()
|
||||
|
||||
// Try different types of valid input
|
||||
metrics.chebyshev_distance([1.0, 0.0], [0.0, 2.0])
|
||||
|> should.equal(Ok(2.0))
|
||||
|
||||
metrics.chebyshev_distance([1.0, 0.0], [2.0, 0.0])
|
||||
|> should.equal(Ok(3.0))
|
||||
|
||||
metrics.chebyshev_distance([-5.0, -10.0, -3.0], [-1.0, -12.0, -3.0])
|
||||
|> should.equal(Ok(4.0))
|
||||
|
||||
metrics.chebyshev_distance([1.0, 2.0, 3.0], [1.0, 2.0, 3.0])
|
||||
|> should.equal(Ok(0.0))
|
||||
}
|
||||
|
|
|
@ -138,6 +138,10 @@ pub fn int_is_perfect_test() {
|
|||
}
|
||||
|
||||
pub fn int_is_prime_test() {
|
||||
// Test a negative integer, i.e., not a natural number
|
||||
predicates.is_prime(-7)
|
||||
|> should.equal(False)
|
||||
|
||||
predicates.is_prime(1)
|
||||
|> should.equal(False)
|
||||
|
||||
|
|
Loading…
Reference in a new issue