From 2ed3924b39ff0263fb0d2468e01df37639c8115c Mon Sep 17 00:00:00 2001 From: Azzaare Date: Tue, 22 Dec 2020 14:57:45 +0900 Subject: [PATCH 01/10] Added scalar functions in transformation layer --- src/CompositionalNetworks.jl | 6 +- src/aggregation.jl | 0 src/arithmetic.jl | 0 src/comparison.jl | 0 src/transformation.jl | 103 +++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/aggregation.jl create mode 100644 src/arithmetic.jl create mode 100644 src/comparison.jl create mode 100644 src/transformation.jl diff --git a/src/CompositionalNetworks.jl b/src/CompositionalNetworks.jl index f38e988..5dc9893 100644 --- a/src/CompositionalNetworks.jl +++ b/src/CompositionalNetworks.jl @@ -1,5 +1,9 @@ module CompositionalNetworks -# Write your package code here. +# Includes layers +include("transformation.jl") +include("arithmetic.jl") +include("aggregation.jl") +include("comparison.jl") end diff --git a/src/aggregation.jl b/src/aggregation.jl new file mode 100644 index 0000000..e69de29 diff --git a/src/arithmetic.jl b/src/arithmetic.jl new file mode 100644 index 0000000..e69de29 diff --git a/src/comparison.jl b/src/comparison.jl new file mode 100644 index 0000000..e69de29 diff --git a/src/transformation.jl b/src/transformation.jl new file mode 100644 index 0000000..21d00e1 --- /dev/null +++ b/src/transformation.jl @@ -0,0 +1,103 @@ +""" + _identity(x::V) +Identity function. Already defined in Julia as `identity`, specialized for vectors. +""" +_identity(x::V) where {T <: Number,V <: AbstractVector{T}} = identity(x) + +""" + _count_eq(i::Int, x::V) + _count_eq_right(i::Int, x::V) + _count_eq_left(i::Int, x::V) +Count the number of elements equal to `x[i]` (optionally to the right/left of `x[i]`). +""" +function _count_eq(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return count(y -> x[i] == y, x) +end +function _count_eq_right(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return _count_eq(i, x[(i + 1):end]) +end +function _count_eq_left(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return _count_eq(i, x[1:(i - 1)]) +end + +""" + _count_greater(i::Int, x::V) + _count_lesser(i::Int, x::V) + _count_g_left(i::Int, x::V) + _count_l_left(i::Int, x::V) + _count_g_right(i::Int, x::V) + _count_l_right(i::Int, x::V) +Count the number of elements greater/lesser than `x[i]` (optionally to the left/right of `x[i]`). +""" +function _count_greater(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return count(y -> x[i] < y, x) +end +function _count_lesser(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return count(y -> x[i] < y, x) +end +function _count_g_left(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return _count_greater(i, x[1:(i - 1)]) +end +function _count_l_left(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return _count_lesser(i, x[1:(i - 1)]) +end +function _count_g_right(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return _count_greater(i, x[(i + 1):end]) +end +function _count_l_right(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return _count_lesser(i, x[(i + 1):end]) +end + +""" + _count_eq_param(param, i::Int, x::V) + _count_l_param(param, i::Int, x::V) + _count_g_param(param, i::Int, x::V) +Count the number of elements equal to (resp. lesser/greater than) `x[i] + param`. +""" +function _count_eq_param(param::T, i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return count(y -> y == x[i] + param, x) +end +function _count_l_param(param::T, i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return count(y -> y < x[i] + param, x) +end +function _count_g_param(param::T, i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return count(y -> y > x[i] + param, x) +end + +""" + _count_eq_param(param, i::Int, x::V) + _count_l_param(param, i::Int, x::V) + _count_g_param(param, i::Int, x::V) +Count the number of elements bounded (not strictly) by `x[i]` and `x[i] + param`. +""" +function _count_bounding_param(param::T, i::Int, x::V +) where {T <: Number,V <: AbstractVector{T}} + return count(y -> x[i] ≤ y ≤ x[i] + param, x) +end + +""" + _val_minus_param(param, i::Int, x::V) + _param_minus_val(param, i::Int, x::V) +Return the difference `x[i] - param` (resp. `param - x[i]`) if positive, `0.0` otherwise. +""" +function _val_minus_param(param::T, i::Int, x::V +) where {T <: Number,V <: AbstractVector{T}} + return max(0.0, x[i] - param) +end +function _param_minus_val(param::T, i::Int, x::V +) where {T <: Number,V <: AbstractVector{T}} + return max(0.0, param - x[i]) +end + +""" + _contiguous_vals_minus(i::Int, x::V) + _contiguous_vals_minus_rev(i::Int, x::V) +Return the difference `x[i] - x[i + 1]` (resp. `x[i + 1] - x[i]`) if positive, `0.0` otherwise. +""" +function _contiguous_vals_minus(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} + return length(x) == i ? 0.0 : _val_minus_param(x[i + 1], i, x::V) +end +function _contiguous_vals_minus_rev(i::Int, x::V +) where {T <: Number,V <: AbstractVector{T}} + return length(x) == i ? 0.0 : _param_minus_val(x[i + 1], i, x::V) +end From 6996a79d163efc4bee9734af0d4e243e174861d1 Mon Sep 17 00:00:00 2001 From: Azzaare Date: Tue, 22 Dec 2020 15:31:14 +0900 Subject: [PATCH 02/10] Added functions to the comparison layer --- src/comparison.jl | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/comparison.jl b/src/comparison.jl index e69de29..cb242e3 100644 --- a/src/comparison.jl +++ b/src/comparison.jl @@ -0,0 +1,51 @@ +""" + _identity(x::T) where T <: Number +Identity function. Already defined in Julia as `identity`, specialized for scalars. +""" +_identity(x::T) where T <: Number = identity(x) + +""" + _abs_diff_val_param(x::T, param::T) +Return the absolute difference between `x` and `param`. +""" +_abs_diff_val_param(x::T, param::T) where T <: Number = abs(x - param) + +""" + _val_minus_param(x::T, param::T) + _param_minus_val(x::T, param::T) +Return the difference `x - param` (resp. `param - x`) if positive, `0.0` otherwise. +""" +_val_minus_param(x::T, param::T) where T <: Number = max(0.0, x - param) +_param_minus_val(x::T, param::T) where T <: Number = max(0.0, param - x) + +""" + _euclidian_param(x::T, param::T, dom_size::T2) + _euclidian(x::T, dom_size::T2) +Compute an euclidian norm , possibly weigthed by `param`, on a scalar. +""" +function _euclidian_param(x::T, param::T, dom_size::T2) where {T <: Number, T2 <: Number} + return x == param ? 0.0 : (1.0 + abs(x - param) \ dom_size) +end +function _euclidian(x::T, dom_size::T2) where {T <: Number, T2 <: Number} + return _euclidian_param(x, 0.0, dom_size) +end + +""" + _abs_diff_val_vars(x::T, vars::V) +Return the absolute difference between `x` and the number of variables. +""" +function _abs_diff_val_vars(x::T, vars::V) where {T <: Number, V <: AbstractVector{T}} + return abs(x - length(vars)) +end + +""" + _val_minus_vars(x::T, vars::V) + _vars_minus_val(x::T, vars::V) +Return the difference `x - length(vars)` (resp. `length(vars) - x`) if positive, `0.0` otherwise. +""" +function _val_minus_vars(x::T, vars::V) where {T <: Number, V <: AbstractVector{T}} + return _val_minus_param(x, length(vars)) +end +function _vars_minus_val(x::T, vars::V) where {T <: Number, V <: AbstractVector{T}} + return _param_minus_val(x, length(vars)) +end \ No newline at end of file From 4e25ab124ef690ffca916dbbc283897a94b4cdb0 Mon Sep 17 00:00:00 2001 From: Azzaare Date: Tue, 22 Dec 2020 15:47:28 +0900 Subject: [PATCH 03/10] Arithmetic layer --- src/arithmetic.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/arithmetic.jl b/src/arithmetic.jl index e69de29..868b04e 100644 --- a/src/arithmetic.jl +++ b/src/arithmetic.jl @@ -0,0 +1,7 @@ +""" + _sum(x::V...) + _prod(x::V...) +Reduce `k = length(x)` vectors through sum/product to a single vector. +""" +_sum(x::V...) where {T <: Number, V <: AbstractVector{T}} = reduce((y, z) -> y .+ z, x) +_prod(x::V...) where {T <: Number, V <: AbstractVector{T}} = reduce((y, z) -> y .* z, x) From 2d586a0560f4659c19dd3d8fbc23882fccf839c5 Mon Sep 17 00:00:00 2001 From: Azzaare Date: Tue, 22 Dec 2020 15:52:23 +0900 Subject: [PATCH 04/10] Aggregation layer --- src/aggregation.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/aggregation.jl b/src/aggregation.jl index e69de29..4b76070 100644 --- a/src/aggregation.jl +++ b/src/aggregation.jl @@ -0,0 +1,11 @@ +""" + _sum(x::V) +Aggregate through `+` a vector into a single scalar. +""" +_sum(x::V) where {T <: Number, V <: AbstractVector{T}} = reduce(+, x) + +""" + _count_positive(x::V) +Count the number of strictly positive elements of `x`. +""" +_count_positive(x::V) where {T <: Number, V <: AbstractVector{T}} = count(y -> y > 0.0, x) \ No newline at end of file From 43bf9e382f7e9f51be077a106add2ae8c3567672 Mon Sep 17 00:00:00 2001 From: Azzaare Date: Tue, 22 Dec 2020 16:01:59 +0900 Subject: [PATCH 05/10] Added layers section in the docs --- docs/make.jl | 6 ++++++ docs/src/aggregation.md | 0 docs/src/arithmetic.md | 0 docs/src/comparison.md | 0 docs/src/transformation.md | 0 5 files changed, 6 insertions(+) create mode 100644 docs/src/aggregation.md create mode 100644 docs/src/arithmetic.md create mode 100644 docs/src/comparison.md create mode 100644 docs/src/transformation.md diff --git a/docs/make.jl b/docs/make.jl index 5a6ec58..d785c95 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -13,6 +13,12 @@ makedocs(; ), pages=[ "Home" => "index.md", + "Layers" => [ + "Transformation" => "transformation.md", + "Arithmetic" => "arithmetic.md", + "Aggregation" => "aggregation.md", + "Comparison" => "comparison.md", + ], ], ) diff --git a/docs/src/aggregation.md b/docs/src/aggregation.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/src/arithmetic.md b/docs/src/arithmetic.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/src/comparison.md b/docs/src/comparison.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/src/transformation.md b/docs/src/transformation.md new file mode 100644 index 0000000..e69de29 From 77092c08082494cbc60f9087da76ffb0b339b4d5 Mon Sep 17 00:00:00 2001 From: Azzaare Date: Tue, 22 Dec 2020 16:52:04 +0900 Subject: [PATCH 06/10] Added first tests. Added @view in some Transformation operation. --- src/transformation.jl | 16 ++++++++-------- test/layers.jl | 10 ++++++++++ test/runtests.jl | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 test/layers.jl diff --git a/src/transformation.jl b/src/transformation.jl index 21d00e1..9aa11b5 100644 --- a/src/transformation.jl +++ b/src/transformation.jl @@ -14,10 +14,10 @@ function _count_eq(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} return count(y -> x[i] == y, x) end function _count_eq_right(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_eq(i, x[(i + 1):end]) + return _count_eq(i, @view x[(i + 1):end]) end function _count_eq_left(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_eq(i, x[1:(i - 1)]) + return _count_eq(i, @view x[1:(i - 1)]) end """ @@ -36,16 +36,16 @@ function _count_lesser(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} return count(y -> x[i] < y, x) end function _count_g_left(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_greater(i, x[1:(i - 1)]) + return _count_greater(i, @view x[1:(i - 1)]) end function _count_l_left(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_lesser(i, x[1:(i - 1)]) + return _count_lesser(i, @view x[1:(i - 1)]) end function _count_g_right(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_greater(i, x[(i + 1):end]) + return _count_greater(i, @view x[(i + 1):end]) end function _count_l_right(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_lesser(i, x[(i + 1):end]) + return _count_lesser(i, @view x[(i + 1):end]) end """ @@ -95,9 +95,9 @@ end Return the difference `x[i] - x[i + 1]` (resp. `x[i + 1] - x[i]`) if positive, `0.0` otherwise. """ function _contiguous_vals_minus(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return length(x) == i ? 0.0 : _val_minus_param(x[i + 1], i, x::V) + return length(x) == i ? 0.0 : _val_minus_param(x[i + 1], i, x) end function _contiguous_vals_minus_rev(i::Int, x::V ) where {T <: Number,V <: AbstractVector{T}} - return length(x) == i ? 0.0 : _param_minus_val(x[i + 1], i, x::V) + return length(x) == i ? 0.0 : _param_minus_val(x[i + 1], i, x) end diff --git a/test/layers.jl b/test/layers.jl new file mode 100644 index 0000000..78d6663 --- /dev/null +++ b/test/layers.jl @@ -0,0 +1,10 @@ +# TODO: large test set + +# Transformation layer +v1 = [1, 5, 2, 4, 3] +v2 = [1, 2, 3, 2, 1] + +@test _identity(v1) == v1 +@test _identity(v2) == v2 + +# @test _count_eq(v) == diff --git a/test/runtests.jl b/test/runtests.jl index 1d3b8a0..6ffc276 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,5 +2,5 @@ using CompositionalNetworks using Test @testset "CompositionalNetworks.jl" begin - # Write your tests here. + include("layers.jl") end From e296b56785690bbfc1b2b2262eaf54745c2d8d16 Mon Sep 17 00:00:00 2001 From: Azzaare Date: Tue, 22 Dec 2020 16:53:55 +0900 Subject: [PATCH 07/10] Added ref ICN = CompositionalNetworks in tests --- test/layers.jl | 4 ++-- test/runtests.jl | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/layers.jl b/test/layers.jl index 78d6663..6728d4e 100644 --- a/test/layers.jl +++ b/test/layers.jl @@ -4,7 +4,7 @@ v1 = [1, 5, 2, 4, 3] v2 = [1, 2, 3, 2, 1] -@test _identity(v1) == v1 -@test _identity(v2) == v2 +@test ICN._identity(v1) == v1 +@test ICN._identity(v2) == v2 # @test _count_eq(v) == diff --git a/test/runtests.jl b/test/runtests.jl index 6ffc276..324e9cf 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,8 @@ using CompositionalNetworks using Test +ICN = CompositionalNetworks + @testset "CompositionalNetworks.jl" begin include("layers.jl") end From 4a9cfdc88e7af038a5ff4520b83554a3a1911104 Mon Sep 17 00:00:00 2001 From: Azzaare Date: Wed, 23 Dec 2020 15:43:59 +0900 Subject: [PATCH 08/10] Added lazy generators for transformation layer --- src/CompositionalNetworks.jl | 6 ++++ src/comparison.jl | 7 ++-- src/transformation.jl | 70 +++++++++++++++++++++--------------- src/utils.jl | 20 +++++++++++ 4 files changed, 69 insertions(+), 34 deletions(-) create mode 100644 src/utils.jl diff --git a/src/CompositionalNetworks.jl b/src/CompositionalNetworks.jl index 5dc9893..89f8f1f 100644 --- a/src/CompositionalNetworks.jl +++ b/src/CompositionalNetworks.jl @@ -1,5 +1,11 @@ module CompositionalNetworks +# Exports utilities +export lazy, lazy_param + +# Include utils +include("utils.jl") + # Includes layers include("transformation.jl") include("arithmetic.jl") diff --git a/src/comparison.jl b/src/comparison.jl index cb242e3..92726ec 100644 --- a/src/comparison.jl +++ b/src/comparison.jl @@ -1,7 +1,4 @@ -""" - _identity(x::T) where T <: Number -Identity function. Already defined in Julia as `identity`, specialized for scalars. -""" +# doc in transformation.jl _identity(x::T) where T <: Number = identity(x) """ @@ -48,4 +45,4 @@ function _val_minus_vars(x::T, vars::V) where {T <: Number, V <: AbstractVector{ end function _vars_minus_val(x::T, vars::V) where {T <: Number, V <: AbstractVector{T}} return _param_minus_val(x, length(vars)) -end \ No newline at end of file +end diff --git a/src/transformation.jl b/src/transformation.jl index 9aa11b5..2cb07ca 100644 --- a/src/transformation.jl +++ b/src/transformation.jl @@ -1,6 +1,7 @@ """ - _identity(x::V) -Identity function. Already defined in Julia as `identity`, specialized for vectors. + _identity(x::V) where {T <: Number,V <: AbstractVector{T}} + _identity(x::T) where T <: Number = identity(x) +Identity function. Already defined in Julia as `identity`, specialized for vectors and scalars. """ _identity(x::V) where {T <: Number,V <: AbstractVector{T}} = identity(x) @@ -8,17 +9,19 @@ _identity(x::V) where {T <: Number,V <: AbstractVector{T}} = identity(x) _count_eq(i::Int, x::V) _count_eq_right(i::Int, x::V) _count_eq_left(i::Int, x::V) -Count the number of elements equal to `x[i]` (optionally to the right/left of `x[i]`). +Count the number of elements equal to `x[i]` (optionally to the right/left of `x[i]`). Extended method to vector `x::V` are generated. """ function _count_eq(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return count(y -> x[i] == y, x) + return count(y -> x[i] == y, x) - 1 end function _count_eq_right(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_eq(i, @view x[(i + 1):end]) + return _count_eq(1, @view x[i:end]) end function _count_eq_left(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_eq(i, @view x[1:(i - 1)]) + return _count_eq(i, @view x[1:i]) end +# Generating vetorized versions +lazy(_count_eq, _count_eq_left, _count_eq_right) """ _count_greater(i::Int, x::V) @@ -27,7 +30,7 @@ end _count_l_left(i::Int, x::V) _count_g_right(i::Int, x::V) _count_l_right(i::Int, x::V) -Count the number of elements greater/lesser than `x[i]` (optionally to the left/right of `x[i]`). +Count the number of elements greater/lesser than `x[i]` (optionally to the left/right of `x[i]`). Extended method to vector with sig `(x::V)` are generated. """ function _count_greater(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} return count(y -> x[i] < y, x) @@ -36,63 +39,70 @@ function _count_lesser(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} return count(y -> x[i] < y, x) end function _count_g_left(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_greater(i, @view x[1:(i - 1)]) + return _count_greater(i, @view x[1:i]) end function _count_l_left(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_lesser(i, @view x[1:(i - 1)]) + return _count_lesser(i, @view x[1:i]) end function _count_g_right(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_greater(i, @view x[(i + 1):end]) + return _count_greater(1, @view x[i:end]) end function _count_l_right(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return _count_lesser(i, @view x[(i + 1):end]) + return _count_lesser(1, @view x[i:end]) end +# Generating vetorized versions +lazy(_count_greater, _count_g_left, _count_g_right) +lazy(_count_lesser, _count_l_left, _count_l_right) """ - _count_eq_param(param, i::Int, x::V) - _count_l_param(param, i::Int, x::V) - _count_g_param(param, i::Int, x::V) -Count the number of elements equal to (resp. lesser/greater than) `x[i] + param`. + _count_eq_param(i::Int, x::V, param::T) + _count_l_param(i::Int, x::V, param::T) + _count_g_param(i::Int, x::V, param::T) +Count the number of elements equal to (resp. lesser/greater than) `x[i] + param`. Extended method to vector with sig `(x::V, param::T)` are generated. """ -function _count_eq_param(param::T, i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} +function _count_eq_param(i::Int, x::V, param::T) where {T <: Number,V <: AbstractVector{T}} return count(y -> y == x[i] + param, x) end -function _count_l_param(param::T, i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} +function _count_l_param(i::Int, x::V, param::T) where {T <: Number,V <: AbstractVector{T}} return count(y -> y < x[i] + param, x) end -function _count_g_param(param::T, i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} +function _count_g_param(i::Int, x::V, param::T) where {T <: Number,V <: AbstractVector{T}} return count(y -> y > x[i] + param, x) end +# Generating vetorized versions +lazy_param(_count_eq_param, _count_l_param, _count_g_param) """ - _count_eq_param(param, i::Int, x::V) - _count_l_param(param, i::Int, x::V) - _count_g_param(param, i::Int, x::V) -Count the number of elements bounded (not strictly) by `x[i]` and `x[i] + param`. + _count_bounding_param(i::Int, x::V, param::T) +Count the number of elements bounded (not strictly) by `x[i]` and `x[i] + param`. An extended method to vector with sig `(x::V, param::T)` is generated. """ -function _count_bounding_param(param::T, i::Int, x::V +function _count_bounding_param(i::Int, x::V, param::T ) where {T <: Number,V <: AbstractVector{T}} return count(y -> x[i] ≤ y ≤ x[i] + param, x) end +# Generating vetorized versions +lazy_param(_count_bounding_param) """ - _val_minus_param(param, i::Int, x::V) - _param_minus_val(param, i::Int, x::V) -Return the difference `x[i] - param` (resp. `param - x[i]`) if positive, `0.0` otherwise. + _val_minus_param(i::Int, x::V, param::T) + _param_minus_val(i::Int, x::V, param::T) +Return the difference `x[i] - param` (resp. `param - x[i]`) if positive, `0.0` otherwise. Extended method to vector with sig `(x::V, param::T)` are generated. """ -function _val_minus_param(param::T, i::Int, x::V +function _val_minus_param(i::Int, x::V, param::T ) where {T <: Number,V <: AbstractVector{T}} return max(0.0, x[i] - param) end -function _param_minus_val(param::T, i::Int, x::V +function _param_minus_val(i::Int, x::V, param::T ) where {T <: Number,V <: AbstractVector{T}} return max(0.0, param - x[i]) end +# Generating vetorized versions +lazy_param(_val_minus_param, _param_minus_val) """ _contiguous_vals_minus(i::Int, x::V) _contiguous_vals_minus_rev(i::Int, x::V) -Return the difference `x[i] - x[i + 1]` (resp. `x[i + 1] - x[i]`) if positive, `0.0` otherwise. +Return the difference `x[i] - x[i + 1]` (resp. `x[i + 1] - x[i]`) if positive, `0.0` otherwise. Extended method to vector with sig `(x::V)` are generated. """ function _contiguous_vals_minus(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} return length(x) == i ? 0.0 : _val_minus_param(x[i + 1], i, x) @@ -101,3 +111,5 @@ function _contiguous_vals_minus_rev(i::Int, x::V ) where {T <: Number,V <: AbstractVector{T}} return length(x) == i ? 0.0 : _param_minus_val(x[i + 1], i, x) end +# Generating vetorized versions +lazy(_contiguous_vals_minus, _contiguous_vals_minus_rev) diff --git a/src/utils.jl b/src/utils.jl new file mode 100644 index 0000000..0afbcac --- /dev/null +++ b/src/utils.jl @@ -0,0 +1,20 @@ + +""" + _map_tr(f, x) + _map_tr(f, x, param) +Return an anonymous function that applies `f` to all elements of `x`, with an optional parameter `param`. +""" +_map_tr(f, x) = ((g, y) -> map(i -> g(i, y), 1:length(y)))(f, x) +_map_tr(f, x, param) = ((g, y, p) -> map(i -> g(i, y, p), 1:length(y)))(f, x, param) + +""" + lazy(funcs::Function...) + lazy_param(funcs::Function...) +Generate methods extended to a vector instead of one of its components. For `lazy` (resp. `lazy_param`) a function `f` should have the following signature: `f(i::Int, x::V)` (resp. `f(i::Int, x::V, param::T)`). +""" +function lazy(funcs::Function...) + foreach(f -> eval(:($f(x) = (y -> _map_tr($f, y))(x))), map(Symbol, funcs)) +end +function lazy_param(funcs::Function...) + foreach(f -> eval(:($f(x, param) = (y -> _map_tr($f, y, param))(x))), map(Symbol, funcs)) +end From 33b6638f6070600ec9bda152acc9461d39b4fa2b Mon Sep 17 00:00:00 2001 From: Azzaare Date: Wed, 23 Dec 2020 17:19:46 +0900 Subject: [PATCH 09/10] Tests for all layers (but 3 functions in comparison --- src/arithmetic.jl | 12 ++-- src/comparison.jl | 2 +- src/transformation.jl | 10 +-- test/layers.jl | 156 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 165 insertions(+), 15 deletions(-) diff --git a/src/arithmetic.jl b/src/arithmetic.jl index 868b04e..6d6ffc6 100644 --- a/src/arithmetic.jl +++ b/src/arithmetic.jl @@ -1,7 +1,11 @@ """ - _sum(x::V...) - _prod(x::V...) + _sum(x::W) where {T <: Number, V <: AbstractVector{T}, W <: AbstractVector{V}} + _prod(x::W) where {T <: Number, V <: AbstractVector{T}, W <: AbstractVector{V}} Reduce `k = length(x)` vectors through sum/product to a single vector. """ -_sum(x::V...) where {T <: Number, V <: AbstractVector{T}} = reduce((y, z) -> y .+ z, x) -_prod(x::V...) where {T <: Number, V <: AbstractVector{T}} = reduce((y, z) -> y .* z, x) +function _sum(x::W) where {T <: Number, V <: AbstractVector{T}, W <: AbstractVector{V}} + return reduce((y, z) -> y .+ z, x) +end +function _prod(x::W) where {T <: Number, V <: AbstractVector{T}, W <: AbstractVector{V}} + return reduce((y, z) -> y .* z, x) +end diff --git a/src/comparison.jl b/src/comparison.jl index 92726ec..5f38c80 100644 --- a/src/comparison.jl +++ b/src/comparison.jl @@ -24,7 +24,7 @@ function _euclidian_param(x::T, param::T, dom_size::T2) where {T <: Number, T2 < return x == param ? 0.0 : (1.0 + abs(x - param) \ dom_size) end function _euclidian(x::T, dom_size::T2) where {T <: Number, T2 <: Number} - return _euclidian_param(x, 0.0, dom_size) + return _euclidian_param(x, zero(T), dom_size) end """ diff --git a/src/transformation.jl b/src/transformation.jl index 2cb07ca..e6050ba 100644 --- a/src/transformation.jl +++ b/src/transformation.jl @@ -36,7 +36,7 @@ function _count_greater(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} return count(y -> x[i] < y, x) end function _count_lesser(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return count(y -> x[i] < y, x) + return count(y -> x[i] > y, x) end function _count_g_left(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} return _count_greater(i, @view x[1:i]) @@ -90,11 +90,11 @@ Return the difference `x[i] - param` (resp. `param - x[i]`) if positive, `0.0` o """ function _val_minus_param(i::Int, x::V, param::T ) where {T <: Number,V <: AbstractVector{T}} - return max(0.0, x[i] - param) + return max(0, x[i] - param) end function _param_minus_val(i::Int, x::V, param::T ) where {T <: Number,V <: AbstractVector{T}} - return max(0.0, param - x[i]) + return max(0, param - x[i]) end # Generating vetorized versions lazy_param(_val_minus_param, _param_minus_val) @@ -105,11 +105,11 @@ lazy_param(_val_minus_param, _param_minus_val) Return the difference `x[i] - x[i + 1]` (resp. `x[i + 1] - x[i]`) if positive, `0.0` otherwise. Extended method to vector with sig `(x::V)` are generated. """ function _contiguous_vals_minus(i::Int, x::V) where {T <: Number,V <: AbstractVector{T}} - return length(x) == i ? 0.0 : _val_minus_param(x[i + 1], i, x) + return length(x) == i ? 0 : _val_minus_param(i, x, x[i + 1]) end function _contiguous_vals_minus_rev(i::Int, x::V ) where {T <: Number,V <: AbstractVector{T}} - return length(x) == i ? 0.0 : _param_minus_val(x[i + 1], i, x) + return length(x) == i ? 0 : _param_minus_val(i, x, x[i + 1]) end # Generating vetorized versions lazy(_contiguous_vals_minus, _contiguous_vals_minus_rev) diff --git a/test/layers.jl b/test/layers.jl index 6728d4e..43886c3 100644 --- a/test/layers.jl +++ b/test/layers.jl @@ -1,10 +1,156 @@ # TODO: large test set # Transformation layer -v1 = [1, 5, 2, 4, 3] -v2 = [1, 2, 3, 2, 1] +data = [ + [1, 5, 2, 4, 3] => 2, + [1, 2, 3, 2, 1] => 2, +] -@test ICN._identity(v1) == v1 -@test ICN._identity(v2) == v2 +# Test transformations without parameters +funcs = Dict( + ICN._identity => [ + data[1].first, + data[2].first, + ], + ICN._count_eq => [ + [0, 0, 0, 0, 0], + [1, 1, 0, 1, 1], + ], + ICN._count_eq_right => [ + [0, 0, 0, 0, 0], + [1, 1, 0, 0, 0], + ], + ICN._count_eq_left => [ + [0, 0, 0, 0, 0], + [0, 0, 0, 1, 1], + ], + ICN._count_greater => [ + [4, 0, 3, 1, 2], + [3, 1, 0, 1, 3], + ], + ICN._count_lesser => [ + [0, 4, 1, 3, 2], + [0, 2, 4, 2, 0], + ], + ICN._count_g_left => [ + [0, 0, 1, 1, 2], + [0, 0, 0, 1, 3], + ], + ICN._count_l_left => [ + [0, 1, 1, 2, 2], + [0, 1, 2, 1, 0], + ], + ICN._count_g_right => [ + [4, 0, 2, 0, 0], + [3, 1, 0, 0, 0], + ], + ICN._count_l_right => [ + [0, 3, 0, 1, 0], + [0, 1, 2, 1, 0], + ], + ICN._contiguous_vals_minus => [ + [0, 3, 0, 1, 0], + [0, 0, 1, 1, 0], + ], + ICN._contiguous_vals_minus_rev => [ + [4, 0, 2, 0, 0], + [1, 1, 0, 0, 0], + ], +) -# @test _count_eq(v) == +for (f, results) in funcs, (key, vals) in enumerate(data) + @test f(vals.first) == results[key] +end + +# Test transformations with parameter +funcs_param = Dict( + ICN._count_eq_param => [ + [1, 0, 1, 0, 1], + [1, 0, 0, 0, 1], + ], + ICN._count_l_param => [ + [2, 5, 3, 5, 4], + [4, 5, 5, 5, 4], + ], + ICN._count_g_param => [ + [2, 0, 1, 0, 0], + [0, 0, 0, 0, 0], + ], + ICN._count_bounding_param => [ + [3, 1, 3, 2, 3], + [5, 3, 1, 3, 5], + ], + ICN._val_minus_param => [ + [0, 3, 0, 2, 1], + [0, 0, 1, 0, 0], + ], + ICN._param_minus_val => [ + [1, 0, 0, 0, 0], + [1, 0, 0, 0, 1], + ], +) + +for (f, results) in funcs_param, (key, vals) in enumerate(data) + @test f(vals.first, vals.second) == results[key] +end + +# arithmetic layer +@test ICN._sum(map(p -> p.first, data)) == [2, 7, 5, 6, 4] +@test ICN._prod(map(p -> p.first, data)) == [1, 10, 6, 8, 3] + +# aggregation layer +@test ICN._sum(data[1].first) == 15 +@test ICN._sum(data[2].first) == 9 + +@test ICN._count_positive(data[1].first) == 5 +@test ICN._count_positive(data[2].first) == 5 +@test ICN._count_positive([1, 0, 1, 0, 1]) == 3 + +# Comparison layer +data = [3 => (1, 5), 5 => (10, 5)] + +funcs = [ + ICN._identity => [3, 5], +] + +# test no param/vars +for (f, results) in funcs, (key, vals) in enumerate(data) + @test f(vals.first) == results[key] +end + +funcs_param = [ + ICN._abs_diff_val_param => [2, 5], + ICN._val_minus_param => [2, 0], + ICN._param_minus_val => [0, 5], +] + +for (f, results) in funcs_param, (key, vals) in enumerate(data) + @test f(vals.first, vals.second[1]) == results[key] +end + +# funcs_vars = [ +# ICN._abs_diff_val_vars => [0, 5], +# ICN._val_minus_vars => [0, 5], +# ICN._vars_minus_val => [0, 5], +# ] + +# for (f, results) in funcs_param, (key, vals) in enumerate(data) +# @test f(vals.first, rand(vals.second[1])) == results[key] +# end + + +funcs_param_dom = [ + ICN._euclidian_param => [3.5, 2.0], +] + +for (f, results) in funcs_param_dom, (key, vals) in enumerate(data) + @test f(vals.first, vals.second[1], vals.second[2]) ≈ results[key] +end + +funcs_dom = [ + ICN._euclidian => [8/3, 2.0], +] + +for (f, results) in funcs_dom, (key, vals) in enumerate(data) + @test f(vals.first, vals.second[2]) ≈ results[key] +end From d211faafc200c08ede170bbea21f1939aaf9a488 Mon Sep 17 00:00:00 2001 From: azzaare Date: Wed, 23 Dec 2020 19:54:08 +0900 Subject: [PATCH 10/10] Tentative coverage 100% --- test/layers.jl | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/test/layers.jl b/test/layers.jl index 43886c3..72bd50a 100644 --- a/test/layers.jl +++ b/test/layers.jl @@ -1,5 +1,3 @@ -# TODO: large test set - # Transformation layer data = [ [1, 5, 2, 4, 3] => 2, @@ -128,15 +126,15 @@ for (f, results) in funcs_param, (key, vals) in enumerate(data) @test f(vals.first, vals.second[1]) == results[key] end -# funcs_vars = [ -# ICN._abs_diff_val_vars => [0, 5], -# ICN._val_minus_vars => [0, 5], -# ICN._vars_minus_val => [0, 5], -# ] +funcs_vars = [ + ICN._abs_diff_val_vars => [2, 0], + ICN._val_minus_vars => [0, 0], + ICN._vars_minus_val => [2, 0], +] -# for (f, results) in funcs_param, (key, vals) in enumerate(data) -# @test f(vals.first, rand(vals.second[1])) == results[key] -# end +for (f, results) in funcs_vars, (key, vals) in enumerate(data) + @test f(vals.first, rand(1:10, vals.second[2])) == results[key] +end funcs_param_dom = [