Skip to content
This repository has been archived by the owner on Dec 3, 2019. It is now read-only.

Commit

Permalink
Updated tests, fixed conversions
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Thatcher committed Jul 10, 2016
1 parent 59a0ab6 commit e8811f3
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 35 deletions.
41 changes: 29 additions & 12 deletions src/functions/compositefunction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -257,42 +257,59 @@ attainsnegative(h::CompositeFunction) = attainsnegative(h.g)
#== Composition Kernels ==#

doc"GaussianKernel(α) = exp(-α⋅‖x-y‖²)"
function GaussianKernel{T<:AbstractFloat}::Argument{T})
function GaussianKernel{T<:AbstractFloat}::Variable{T})
CompositeFunction(ExponentialClass(α), SquaredEuclidean{T}())
end
function GaussianKernel{T}::T=1.0)
T <: AbstractFloat ? GaussianKernel(α) : GaussianKernel(convert(Float64, α))
function GaussianKernel{T}::Argument{T}=1.0)
GaussianKernel(Variable{T <: AbstractFloat ? T : Float64}(α))
end
SquaredExponentialKernel = GaussianKernel
RadialBasisKernel = GaussianKernel

doc"LaplacianKernel(α) = exp(α⋅‖x-y‖)"
function LaplacianKernel{T<:AbstractFloat}::Argument{T})
CompositeFunction(GammaExponentialClass(α, convert(T, 0.5)), SquaredEuclidean{T}())
function LaplacianKernel{T<:AbstractFloat}::Variable{T})
CompositeFunction(GammaExponentialClass(α, Variable{T}(0.5)), SquaredEuclidean{T}())
end
function LaplacianKernel{T}::T=1.0)
T <: AbstractFloat ? LaplacianKernel(α) : LaplacianKernel(convert(Argument{Float64}, α))
function LaplacianKernel{T<:Real}::Argument{T}=1.0)
LaplacianKernel(Variable{T <: AbstractFloat ? T : Float64}(α))
end

doc"PeriodicKernel(α,p) = exp(-α⋅Σⱼsin²(p(xⱼ-yⱼ)))"
function PeriodicKernel{T<:AbstractFloat}::Argument{T}, p::Argument{T})
function PeriodicKernel{T<:AbstractFloat}::Variable{T}, p::Variable{T})
CompositeFunction(ExponentialClass(α), SineSquaredKernel(p))
end
function PeriodicKernel{T1,T2}::Argument{T1} = 1.0, p::Argument{T2} = convert(Float64,π))
function PeriodicKernel{T1<:Real,T2<:Real}(
α::Argument{T1} = 1.0,
p::Argument{T2} = convert(T1 <: AbstractFloat ? T1 : Float64,π)
)
Tmax = promote_type(T1, T2)
T = Tmax <: AbstractFloat ? Tmax : Float64
PeriodicKernel(convert(Argument{T}, α), convert(Argument{T}, p))
PeriodicKernel(Variable{T}(α), Variable{T}(p))
end

doc"RationalQuadraticKernel(α,β) = (1 + α⋅‖x-y‖²)⁻ᵝ"
function RationalQuadraticKernel{T<:AbstractFloat}::Argument{T} = 1.0, β::Argument{T} = one(T))
function RationalQuadraticKernel{T<:AbstractFloat}::Variable{T}, β::Variable{T})
CompositeFunction(RationalClass(α, β), SquaredEuclidean{T}())
end
function RationalQuadraticKernel{T1<:Real,T2<:Real}(
α::Argument{T1} = 1.0,
β::Argument{T2} =one(T1)
)
Tmax = promote_type(T1, T2)
T = Tmax <: AbstractFloat ? Tmax : Float64
RationalQuadraticKernel(Variable{T}(α), Variable{T}(β))
end

doc"MatérnKernel(ν,θ) = 2ᵛ⁻¹(√(2ν)‖x-y‖²/θ)ᵛKᵥ(√(2ν)‖x-y‖²/θ)/Γ(ν)"
function MaternKernel{T<:AbstractFloat}::Argument{T} = 1.0, θ::Argument{T} = one(T))
function MaternKernel{T<:AbstractFloat}::Variable{T}, θ::Variable{T})
CompositeFunction(MaternClass(ν, θ), SquaredEuclidean{T}())
end
function MaternKernel{T1<:Real,T2<:Real}::Argument{T1} = 1.0, θ::Argument{T2} = one(T1))
Tmax = promote_type(T1, T2)
T = Tmax <: AbstractFloat ? Tmax : Float64
MaternKernel(Variable{T}(ν), Variable{T}(θ))
end

MatérnKernel = MaternKernel

doc"PolynomialKernel(a,c,d) = (a⋅xᵀy + c)ᵈ"
Expand Down
1 change: 1 addition & 0 deletions src/hyperparameter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ fixed{T<:Real}(v::T) = Variable{T}(v, true)
eltype{T<:Real}(::Variable{T}) = T

convert{T<:Real}(::Type{Variable{T}}, var::Variable) = Variable(convert(T, var.value), var.isfixed)
convert{T<:Real}(::Type{Variable{T}}, var::Real) = Variable(convert(T, var), false)

typealias Argument{T<:Real} Union{T,Variable{T}}

Expand Down
73 changes: 72 additions & 1 deletion src/meta.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
function promote_type_float(T_i::DataType...)
T_max = promote_type(T_i...)
T_max <: AbstractFloat ? T_max : Float64
end

function promote_type_int(U_i::DataType...)
U_max = promote_type(U_i...)
U_max <: Signed ? U_max : Int64
end


# Checks to make sure the fields in the datatype are of type Parameter{T} or Parameter{U} where
# T<:AbstractFloat and U<:Integer
function fieldparameters(obj::DataType)
Expand Down Expand Up @@ -36,6 +47,65 @@ function fieldparameters(obj::DataType)
return (fields, field_parameters)
end

function promote_code_block(obj::DataType, cstr_params, field_params)
promote_T = Expr(:call, :promote_type_float, cstr_params[field_params .== :T]...)
if length(obj.parameters) == 1
return :(T = $promote_T)
else
promote_U = Expr(:call, :promote_type_int, cstr_params[field_params .== :U]...)
return Expr(:block, :(T = $promote_T), :(U = $promote_U))
end
end

function fieldparameters_constructor(obj::DataType)
fields, field_params = fieldparameters(obj)
n = length(fields)
counter = [1,1] # T count, U count
constructor_params = Array(Symbol, n)
constructor_types = Array(Union{Symbol,Expr}, n)
for i in eachindex(field_params)
param_sym = field_params[i]
param_idx = param_sym == :T ? 1 : 2
constructor_params[i] = Symbol(string(param_sym, counter[param_idx]))
if counter[param_idx] == 1
constructor_types[i] = param_idx == 1 ? :Float64 : :Int64
else
preceding_params = (constructor_params[1:i-1])[field_params[1:i-1] .== param_sym]
promotion = param_idx == 1 ? :promote_type_float : :promote_type_int
constructor_types[i] = Expr(:call, promotion, preceding_params...)
end
counter[param_idx] += 1
end
(fields, field_params, constructor_params, constructor_types)
end

function generate_outer_constructor2(obj::DataType, default_values::Tuple{Vararg{Real}})
# (:a,:b,:c,:d), [:T, :U, :T, :U], [:T1, :U1, :T2, :U2],
# [:Float64, :Int64, promote_type_float(T1), promote_type_int(U1)]
fields, field_params, cstr_params, cstr_types = fieldparameters_constructor(obj)

if (n = length(default_values)) != length(fields)
error("Default count does not match field count")
end

# [:(T1 <: Real), :(T2 <: Real), :(U1 <: Real)
defn_params = [Expr(:(<:), cstr_params[i], :Real) for i = 1:n]

# (a::Argument{T1}=convert(Float64,x), b::Argument{T2}=convert(T1,x)...
defn_args = [Expr(:kw, :($(fields[i])::Argument{$(cstr_params[i])}),
:(convert($(cstr_types[i]), $(default_values[i])))) for i = 1:n]

# (Variable{T}(a), Variable{T}(b), Variable{U}(c))
call_args = [:(Variable{$(field_params[i])}($(fields[i]))) for i = 1:n]

block_definition = Expr(:call, Expr(:curly, obj.name.name, defn_params...), defn_args...)
block_promotion = promote_code_block(obj, cstr_params, field_params)
block_call = Expr(:call, Expr(:curly, obj.name.name, [p.name for p in obj.parameters]...), call_args...)

return Expr(:function, block_definition, Expr(:block, block_promotion, block_call))
end


function generate_conversions(obj::DataType)
fields, field_parameters = fieldparameters(obj)
obj_sym = obj.name.name
Expand Down Expand Up @@ -91,7 +161,8 @@ function generate_outer_constructor(obj::DataType, defaults::Tuple{Vararg{Real}}
Expr(:call, Expr(:curly, obj_sym, type_params...), type_args...))
end


macro outer_constructor(obj, defaults)
eval(generate_outer_constructor(eval(obj), eval(defaults)))
eval(generate_outer_constructor2(eval(obj), eval(defaults)))
eval(generate_conversions(eval(obj)))
end
6 changes: 3 additions & 3 deletions test/functions/compositefunction.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
info("Testing ", MOD.CompositionClass)
info("Testing ", MOD.CompositionClass.name.name)
steps = length(composition_classes)
counter = 0
for class_obj in composition_classes
Expand Down Expand Up @@ -63,10 +63,10 @@ for class_obj in composition_classes
show(DevNull, g)

counter += 1
info("[", @sprintf("%3.0f", counter/steps*100), "%] ", class_obj)
info("[", @sprintf("%3.0f", counter/steps*100), "%] ", class_obj.name.name)
end

info("Testing ", MOD.CompositeFunction)
info("Testing ", MOD.CompositeFunction.name.name)
for class_obj in composition_classes
g = (class_obj)()
for f_obj in pairwise_functions
Expand Down
4 changes: 2 additions & 2 deletions test/functions/pairwisefunction.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
info("Testing ", MOD.PairwiseFunction)
info("Testing ", MOD.PairwiseFunction.name.name)
steps = length(pairwise_functions)
counter = 0
for f_obj in pairwise_functions
Expand Down Expand Up @@ -63,5 +63,5 @@ for f_obj in pairwise_functions
show(DevNull, f)

counter += 1
info("[", @sprintf("%3.0f", counter/steps*100), "%] ", f_obj)
info("[", @sprintf("%3.0f", counter/steps*100), "%] ", f_obj.name.name)
end
6 changes: 3 additions & 3 deletions test/functions/pointwisefunction.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
info("Testing ", AffineFunction)
info("Testing ", AffineFunction.name.name)
for f_obj in (pairwise_functions..., composite_functions...)
for T in FloatingPointTypes

Expand Down Expand Up @@ -76,7 +76,7 @@ for f_obj in (pairwise_functions..., composite_functions...)
end


info("Testing ", FunctionSum)
info("Testing ", FunctionSum.name.name)
for f_obj1 in (pairwise_functions..., composite_functions...)
for f_obj2 in (pairwise_functions..., composite_functions...)
for T in FloatingPointTypes
Expand Down Expand Up @@ -137,7 +137,7 @@ for f_obj1 in (pairwise_functions..., composite_functions...)
end
end

info("Testing ", FunctionProduct)
info("Testing ", FunctionProduct.name.name)
for f_obj1 in (pairwise_functions..., composite_functions...)
for f_obj2 in (pairwise_functions..., composite_functions...)
for T in FloatingPointTypes
Expand Down
8 changes: 4 additions & 4 deletions test/hyperparameter.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
info("Testing ", Bound)
info("Testing ", Bound.name.name)
for T in (FloatingPointTypes..., IntegerTypes...)
for isopen in (true, false)
B = Bound(one(T), isopen)
Expand All @@ -18,7 +18,7 @@ for T in (FloatingPointTypes..., IntegerTypes...)
end
end

info("Testing ", Interval)
info("Testing ", Interval.name.name)
for T in (FloatingPointTypes..., IntegerTypes...)
for lisopen in (true, false), uisopen in (true, false)
Bl = Bound(zero(T), lisopen)
Expand Down Expand Up @@ -113,7 +113,7 @@ for T in (FloatingPointTypes..., IntegerTypes...)
end
end

info("Testing ", Variable)
info("Testing ", Variable.name.name)
for T in (FloatingPointTypes..., IntegerTypes...)

v = Variable(one(T))
Expand All @@ -135,7 +135,7 @@ for T in (FloatingPointTypes..., IntegerTypes...)
end
end

info("Testing ", HyperParameter)
info("Testing ", HyperParameter.name.name)
for T in (FloatingPointTypes..., IntegerTypes...)
I = rightbounded(one(T), :open)

Expand Down
21 changes: 11 additions & 10 deletions test/pairwise.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ test_pairwise_functions = [(f_obj)() for f_obj in pairwise_functions]
test_composite_functions = [(f_obj)() for f_obj in composite_functions]
test_sample = [SquaredEuclidean(), ChiSquared(), ScalarProduct(), GaussianKernel()]

info("Testing ", MOD.unsafe_pairwise)
info("Testing ", MOD.unsafe_pairwise.env.name)
for T in FloatingPointTypes
x = rand(T,p)
y = rand(T,p)
Expand Down Expand Up @@ -43,7 +43,7 @@ for T in FloatingPointTypes
end
end

info("Testing ", MOD.pairwise)
info("Testing ", MOD.pairwise.env.name)
for T in FloatingPointTypes
x = rand(T,p)
y = rand(T,p)
Expand Down Expand Up @@ -98,7 +98,7 @@ for T in FloatingPointTypes
end
end

info("Testing ", MOD.dotvectors!)
info("Testing ", MOD.dotvectors!.env.name)
for T in FloatingPointTypes
Set_X = [rand(T, p) for i = 1:n]
Set_Y = [rand(T,p) for i = 1:m]
Expand All @@ -117,7 +117,7 @@ for T in FloatingPointTypes
@test_throws DimensionMismatch MOD.dotvectors!(Val{:col}, Array(T,2), Array(T,2,3))
end

info("Testing ", MOD.gramian!)
info("Testing ", MOD.gramian!.env.name)
for T in FloatingPointTypes
Set_X = [rand(T, p) for i = 1:n]
Set_Y = [rand(T,p) for i = 1:m]
Expand Down Expand Up @@ -154,7 +154,7 @@ for T in FloatingPointTypes

end

info("Testing ", MOD.squared_distance!)
info("Testing ", MOD.squared_distance!.env.name)
for T in FloatingPointTypes
Set_X = [rand(T,p) for i = 1:n]
Set_Y = [rand(T,p) for i = 1:m]
Expand Down Expand Up @@ -184,7 +184,7 @@ for T in FloatingPointTypes
@test_throws DimensionMismatch MOD.squared_distance!(Array(T,3,4), Array(T,3), Array(T,5))
end

info("Testing ", MOD.rectangular_compose!)
info("Testing ", MOD.rectangular_compose!.env.name)
for f_obj in composition_classes
for T in FloatingPointTypes
X = rand(T, n, m)
Expand All @@ -195,7 +195,7 @@ for f_obj in composition_classes
end
end

info("Testing ", MOD.symmetric_compose!)
info("Testing ", MOD.symmetric_compose!.env.name)
for f_obj in composition_classes
for T in FloatingPointTypes
X = rand(T, n, n)
Expand All @@ -209,15 +209,16 @@ for f_obj in composition_classes
end
end

info("Testing ", MOD.pairwisematrix!)
info("Testing ", MOD.pairwisematrix!.env.name)
test_set = (test_pairwise_functions..., test_composite_functions...,
[2*f+1 for f in test_sample]...,
[f1+f2 for f1 in test_sample, f2 in test_sample]...,
[f1*f2 for f1 in test_sample, f2 in test_sample]...)
steps = length(test_set)
counter = 0
for f_test in test_set
info("[", @sprintf("%3.0f", counter/steps*100), "%] Case ", @sprintf("%2.0f", counter+1), "/", steps)
info("[", @sprintf("%3.0f", counter/steps*100), "%] Case ", @sprintf("%2.0f", counter+1), "/",
steps, " - ", test_print(f_test))
for T in FloatingPointTypes
Set_X = [rand(T,p) for i = 1:n]
Set_Y = [rand(T,p) for i = 1:m]
Expand Down Expand Up @@ -256,7 +257,7 @@ for f_test in test_set
end
info("[100%] Done")

info("Testing ", MOD.pairwisematrix)
info("Testing ", MOD.pairwisematrix.env.name)
test_set = test_sample
steps = length(test_set)
counter = 0
Expand Down
8 changes: 8 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ FloatingPointTypes = (Float32, Float64)
IntegerTypes = (Int32, UInt32, Int64, UInt64)
MOD = MLKernels

test_print(f::RealFunction) = string(typeof(f).name)
test_print(h::AffineFunction) = string(typeof(h).name, "(", typeof(h.f).name.name, ")")
test_print(h::CompositeFunction) = string(typeof(h).name.name, "(", typeof(h.g).name.name, ",",
typeof(h.f).name.name, ")")
test_print(h::FunctionSum) = string(typeof(h).name.name, "(", typeof(h.g).name.name, ",",
typeof(h.f).name.name, ")")
test_print(h::FunctionProduct) = string(typeof(h).name.name, "(", typeof(h.g).name.name, ",",
typeof(h.f).name.name, ")")
#=
module MLKTest
Expand Down

0 comments on commit e8811f3

Please sign in to comment.