Skip to content

Commit

Permalink
taylor_expand function for Taylor1 and TaylorN (#121)
Browse files Browse the repository at this point in the history
* Added function and macro `taylor_expand` for expanding arbitraty functions.

* Deleted macros and set order as keyword argument so methods doesnt clash

`taylor_expand(f,x0::Int64)` and `taylor_expand(f,order)` clashed.

* Added some tests for `taylor_expand`.

* un-exported taylor_expand macros.

* Updated taylor_expand tests.

* Added taylor_expand method for TaylorN and warning if number of variables is changed.

* Fix travis issue for taylor_expand (hopefully).

* Added taylor_expand! and tests for Taylor1.

Followed suggestion from @lbenet.

* Add function-like behavior for Taylor1, TaylorN, HomogeneousPolynomial (#118)

* Add function-like behavior for Taylor1

* Relocate new code

* Add function-like behavior for TaylorN

* Fix TaylorN functor methods

* Add tests for Taylor1

* Add more Taylor1 tests

* Add TaylorN tests; more Taylor1 tests; add missing evaluate methods

* Add function-like behavior for HomogeneousPolynomial and corresponding tests

* Add missing tests for HomogeneousPolynomial

* Add another test for Taylor1s

* Fix test

* Add extra evaluate method for Taylor1 (suggested by @blas-ko)

* Add an evaluate test for mixtures (more to come)

* Add tests for mixtures; add/fix evaluate methods

* A small fix

* Add missing evaluate methods for mixtures and tests

* Update docs

* Add evaluate method and tests

* Fix new method

* Update docstrings

* Changes suggested by @lbenet 's review

* Added method for evaluating a TaylorN with an array of TaylorNs.

* Added taylor_expand! method for TaylorN

* Added some test for taylor_expand!

* Documentation for taylor_expand and taylor_expand!

* Added function and macro `taylor_expand` for expanding arbitraty functions.

* Deleted macros and set order as keyword argument so methods doesnt clash

`taylor_expand(f,x0::Int64)` and `taylor_expand(f,order)` clashed.

* Added some tests for `taylor_expand`.

* un-exported taylor_expand macros.

* Updated taylor_expand tests.

* Added taylor_expand method for TaylorN and warning if number of variables is changed.

* Fix travis issue for taylor_expand (hopefully).

* Added taylor_expand! and tests for Taylor1.

Followed suggestion from @lbenet.

* Add function-like behavior for Taylor1, TaylorN, HomogeneousPolynomial (#118)

* Add function-like behavior for Taylor1

* Relocate new code

* Add function-like behavior for TaylorN

* Fix TaylorN functor methods

* Add tests for Taylor1

* Add more Taylor1 tests

* Add TaylorN tests; more Taylor1 tests; add missing evaluate methods

* Add function-like behavior for HomogeneousPolynomial and corresponding tests

* Add missing tests for HomogeneousPolynomial

* Add another test for Taylor1s

* Fix test

* Add extra evaluate method for Taylor1 (suggested by @blas-ko)

* Add an evaluate test for mixtures (more to come)

* Add tests for mixtures; add/fix evaluate methods

* A small fix

* Add missing evaluate methods for mixtures and tests

* Update docs

* Add evaluate method and tests

* Fix new method

* Update docstrings

* Changes suggested by @lbenet 's review

* Added method for evaluating a TaylorN with an array of TaylorNs.

* Added taylor_expand! method for TaylorN

* Added some test for taylor_expand!

* Documentation for taylor_expand and taylor_expand!

* Corrected silly mistake from rebasing.

* Rearanged taylor_expand tests to another place.

They use set_variables internally.

* called coeff_table directly so it doesn't make a copy.

* changed docs for taylor_expand

* Changed taylor_expand for TaylorN.

* It doesn't use set_variables() anymore.
* typeof(x0) is preserved if possible.

* Changed taylor_expand! for update!

* Added 1 more test...

* Little performance and compatibility fix for taylor_expand
  • Loading branch information
blas-ko authored and lbenet committed Oct 8, 2017
1 parent 2111846 commit 909689b
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 30 deletions.
3 changes: 2 additions & 1 deletion src/TaylorSeries.jl
Expand Up @@ -46,7 +46,8 @@ export get_coeff, derivative, integrate,
show_params_TaylorN,
get_order, get_numvars,
set_variables, get_variables,
∇, jacobian, jacobian!, hessian, hessian!
∇, jacobian, jacobian!, hessian, hessian!,
taylor_expand, update!

include("parameters.jl")
include("hash_tables.jl")
Expand Down
63 changes: 48 additions & 15 deletions src/evaluate.jl
Expand Up @@ -79,7 +79,7 @@ function evaluate!{T<:Number, S<:Number}(x::Array{Taylor1{T},1}, δt::S, x0::Uni
nothing
end

"""
doc"""
evaluate(a, x)
Substitute `x::Taylor1` as independent variable in a `a::Taylor1` polynomial.
Expand Down Expand Up @@ -137,6 +137,15 @@ function evaluate!{T<:NumberNotSeriesN}(x::Array{TaylorN{T},1}, δx::Array{Taylo
nothing
end

function evaluate!{T<:NumberNotSeriesN}(x::Array{TaylorN{T},1}, δx::Array{TaylorN{T},1},
x0::Array{TaylorN{T},1})
@assert length(x) == length(x0)
@inbounds for i in eachindex(x)
x0[i] = evaluate( x[i], δx )
end
nothing
end

function evaluate!{T<:Number}(x::Array{Taylor1{TaylorN{T}},1}, δt::T,
x0::Array{TaylorN{T},1})
@assert length(x) == length(x0)
Expand All @@ -146,7 +155,7 @@ function evaluate!{T<:Number}(x::Array{Taylor1{TaylorN{T}},1}, δt::T,
nothing
end

"""
doc"""
evaluate(a, [vals])
Evaluate a `HomogeneousPolynomial` polynomial at `vals`. If `vals` is ommitted,
Expand Down Expand Up @@ -180,7 +189,7 @@ evaluate(a::HomogeneousPolynomial) = zero(a[1])

(p::HomogeneousPolynomial)() = evaluate(p)

"""
doc"""
evaluate(a, [vals])
Evaluate the `TaylorN` polynomial `a` at `vals`.
Expand All @@ -193,16 +202,15 @@ function evaluate{T<:Number,S<:NumberNotSeries}(a::TaylorN{T},
@assert length(vals) == get_numvars()

num_vars = get_numvars()
ct = coeff_table
R = promote_type(T,S)
a_length = length(a)
suma = zeros(R,a_length)
for homPol in 1:length(a)
sun = zero(R)
for (i,a_coeff) in enumerate(a.coeffs[homPol].coeffs)
tmp = vals[1]^(ct[homPol][i][1])
tmp = vals[1]^(coeff_table[homPol][i][1])
for n in 2:num_vars
tmp *= vals[n]^(ct[homPol][i][n])
tmp *= vals[n]^(coeff_table[homPol][i][n])
end
sun += a_coeff * tmp
end
Expand All @@ -217,18 +225,16 @@ function evaluate{T<:Number,S<:NumberNotSeries}(a::TaylorN{T},
@assert length(vals) == get_numvars()

num_vars = get_numvars()
ct = coeff_table
R = promote_type(T,S)
a_length = length(a)
ord = maximum( get_order.(vals) )
suma = Taylor1(zeros(R, ord))

for homPol in 1:length(a)
sun = zero(R)
for (i,a_coeff) in enumerate(a.coeffs[homPol].coeffs)
tmp = vals[1]^(ct[homPol][i][1])
tmp = vals[1]^(coeff_table[homPol][i][1])
for n in 2:num_vars
tmp *= vals[n]^(ct[homPol][i][n])
tmp *= vals[n]^(coeff_table[homPol][i][n])
end
suma += a_coeff * tmp
end
Expand All @@ -242,17 +248,15 @@ function evaluate{T<:NumberNotSeries}(a::TaylorN{Taylor1{T}},
@assert length(vals) == get_numvars()

num_vars = get_numvars()
ct = coeff_table
a_length = length(a)
ord = maximum( get_order.(vals) )
suma = Taylor1(zeros(T, ord))

for homPol in 1:length(a)
sun = zero(Taylor1{T})
for (i,a_coeff) in enumerate(a.coeffs[homPol].coeffs)
tmp = vals[1]^(ct[homPol][i][1])
tmp = vals[1]^(coeff_table[homPol][i][1])
for n in 2:num_vars
tmp *= vals[n]^(ct[homPol][i][n])
tmp *= vals[n]^(coeff_table[homPol][i][n])
end
suma += a_coeff * tmp
end
Expand All @@ -261,6 +265,30 @@ function evaluate{T<:NumberNotSeries}(a::TaylorN{Taylor1{T}},
return suma
end

function evaluate{T<:Number,S<:NumberNotSeries}(a::TaylorN{T},
vals::Array{TaylorN{S},1})
@assert length(vals) == get_numvars()

num_vars = get_numvars()
R = promote_type(T,eltype(S))
a_length = length(a)
ord = maximum( get_order.(vals) )
suma = zero(TaylorN{R})

for homPol in 1:length(a)
for (i,a_coeff) in enumerate(a.coeffs[homPol].coeffs)
tmp = vals[1]^(coeff_table[homPol][i][1])
for n in 2:num_vars
tmp *= vals[n]^(coeff_table[homPol][i][n])
end
suma += a_coeff * tmp
end
end

return suma
end


evaluate{T<:Number}(a::TaylorN{T}) = a[1][1]

function evaluate{T<:Number}(x::Array{TaylorN{T},1}, δx::Array{T,1})
Expand All @@ -275,6 +303,12 @@ function evaluate{T<:NumberNotSeriesN}(x::Array{TaylorN{T},1}, δx::Array{Taylor
return x0
end

function evaluate{T<:NumberNotSeriesN}(x::Array{TaylorN{T},1}, δx::Array{TaylorN{T},1})
x0 = Array{TaylorN{T}}( length(x) )
evaluate!( x, δx, x0 )
return x0
end

evaluate{T<:Number}(x::Array{TaylorN{T},1}) = evaluate.(x)

#function-like behavior for TaylorN
Expand All @@ -286,4 +320,3 @@ evaluate{T<:Number}(x::Array{TaylorN{T},1}) = evaluate.(x)
(p::Array{TaylorN{T},1}){T<:Number}(x) = evaluate(p, x)

(p::Array{TaylorN{T},1}){T<:Number}() = evaluate(p)

70 changes: 70 additions & 0 deletions src/other_functions.jl
Expand Up @@ -129,6 +129,7 @@ function abs{T<:Real}(a::Taylor1{TaylorN{T}})
(abs(x) is not differentiable at x=0)."""))
end
end

doc"""
abs(a)
Expand Down Expand Up @@ -178,3 +179,72 @@ polynomials. For more details, see [`Base.isapprox`](@ref).
function isapprox{T<:AbstractSeries,S<:AbstractSeries}(x::T, y::S; rtol::Real=rtoldefault(x,y), atol::Real=0, nans::Bool=false)
x == y || (isfinite(x) && isfinite(y) && norm(x-y,1) <= atol + rtol*max(norm(x,1), norm(y,1))) || (nans && isnan(x) && isnan(y))
end


#taylor_expand function for Taylor1
doc"""
taylor_expand(f ,x0 ;order)
Makes a Taylor expansion of the function `f` around the point `x0`. If x0 is a scalar,
a `Taylor1` expansion will be done. If `x0` is a vector, a `TaylorN` expansion will be
computed. If the dimension of x0 (`length(x0)`) is different from the variables set for
`TaylorN` (`get_numvars()`), an `AssertionError` will be thrown.
"""
function taylor_expand(f::Function; order::Int64=15)
a = Taylor1(order)
return f(a)
end

function taylor_expand{T<:Number}(f::Function, x0::T; order::Int64=15)
a = Taylor1([x0, one(T)], order)
return f(a)
end

#taylor_expand function for TaylorN
function taylor_expand{T<:Number}(f::Function, x0::Vector{T}; order::Int64=get_order()) #a Taylor expansion around x0
ll = length(x0)
@assert ll == get_numvars() && order <= get_order()
X = Array{TaylorN{T}}(ll)

for i in eachindex(X)
X[i] = x0[i] + TaylorN(T, i, order=order)
end

return f( X )
end

function taylor_expand(f::Function, x0...; order::Int64=get_order()) #a Taylor expansion around x0
x0 = promote(x0...)
T = eltype(x0[1])
ll = length(x0)
@assert ll == get_numvars() && order <= get_order()
X = Array{TaylorN{T}}(ll)

for i in eachindex(X)
X[i] = x0[i] + TaylorN(T, i, order=order)
end

return f( X... )
end

#update! function for Taylor1
doc"""
update!(a,x0;order)
Takes `a <: Union{Taylo1,TaylorN}` and expands it around the coordinate `x0`.
"""
function update!{T<:Number}(a::Taylor1, x0::T)
a.coeffs .= evaluate(a, Taylor1([x0,one(x0)], a.order) ).coeffs
nothing
end

#update! function for TaylorN
function update!{T<:Number}(a::TaylorN,vals::Vector{T})
a.coeffs .= evaluate(a,get_variables().+vals).coeffs
nothing
end

function update!(a::Union{Taylor1,TaylorN})
#shifting around zero shouldn't change anything...
nothing
end
42 changes: 28 additions & 14 deletions test/manyvariables.jl
Expand Up @@ -337,6 +337,21 @@ end
hessian!(hes2,g1(xT+1,yT-1)-g2(xT+1,yT-1))
@test hes1 == hes2

@test string(-xH) == " - 1 x₁"
@test string(xT^2) == " 1 x₁² + 𝒪(‖x‖¹⁸)"
@test string(1im*yT) == " ( 1 im ) x₂ + 𝒪(‖x‖¹⁸)"
@test string(xT-im*yT) == " ( 1 ) x₁ - ( 1 im ) x₂ + 𝒪(‖x‖¹⁸)"

@test_throws ArgumentError abs(xT)
@test_throws AssertionError 1/x
@test_throws AssertionError zero(x)/zero(x)
@test_throws ArgumentError sqrt(x)
@test_throws AssertionError x^(-2)
@test_throws ArgumentError log(x)
@test_throws AssertionError cos(x)/sin(y)
@test_throws BoundsError xH[20]
@test_throws BoundsError xT[20]

a = 3x + 4y +6x^2 + 8x*y
@test typeof( norm(x) ) == Float64
@test norm(x) > 0
Expand Down Expand Up @@ -367,20 +382,18 @@ end
@test a[2] b[2]
@test a b

@test string(-xH) == " - 1 x₁"
@test string(xT^2) == " 1 x₁² + 𝒪(‖x‖¹⁸)"
@test string(1im*yT) == " ( 1 im ) x₂ + 𝒪(‖x‖¹⁸)"
@test string(xT-im*yT) == " ( 1 ) x₁ - ( 1 im ) x₂ + 𝒪(‖x‖¹⁸)"

@test_throws ArgumentError abs(xT)
@test_throws AssertionError 1/x
@test_throws AssertionError zero(x)/zero(x)
@test_throws ArgumentError sqrt(x)
@test_throws AssertionError x^(-2)
@test_throws ArgumentError log(x)
@test_throws AssertionError cos(x)/sin(y)
@test_throws BoundsError xH[20]
@test_throws BoundsError xT[20]
f11(a,b) = (a+b)^a - cos(a*b)*b
f22(a) = (a[1] + a[2])^a[1] - cos(a[1]*a[2])*a[2]
@test taylor_expand(f11,1.,2.) == taylor_expand(f22,[1,2.])
@test evaluate(taylor_expand(x->x[1] + x[2],[1,2])) == 3.0
f33(x,y) = 3x+y
@test eltype(taylor_expand(f33,1,1)) == eltype(1)
x,y = get_variables()
xysq = x^2 + y^2
update!(xysq,[1.0,-2.0])
@test xysq == (x+1.0)^2 + (y-2.0)^2
update!(xysq,[-1.0,2.0])
@test xysq == x^2 + y^2

#test function-like behavior for TaylorN
@test exy() == 1
Expand All @@ -390,6 +403,7 @@ end
@test asin(sin(xT+yT))([1.0,0.5]) == 1.5
@test ( -sinh(xT+yT)^2 + cosh(xT+yT)^2 )(rand(2)) == 1
@test ( -sinh(xT+yT)^2 + cosh(xT+yT)^2 )(zeros(2)) == 1
#number of variables changed to 4...
dx = set_variables("x", numvars=4, order=10)
P = sin.(dx)
v = [1.0,2,3,4]
Expand Down
12 changes: 12 additions & 0 deletions test/onevariable.jl
Expand Up @@ -154,6 +154,18 @@ end
@test abs(ta(1)) == ta(1)
@test abs(ta(-1.0)) == -ta(-1.0)


@test taylor_expand(x->2x,order=10) == 2*Taylor1(10)
@test taylor_expand(x->x^2+1) == Taylor1(15)*Taylor1(15) + 1
@test evaluate(taylor_expand(cos,0.)) == cos(0.)
@test evaluate(taylor_expand(tan,pi/4)) == tan(pi/4)
@test eltype(taylor_expand(x->x^2+1,1)) == eltype(1)
tsq = t^2
update!(tsq,2.0)
@test tsq == (t+2.0)^2
update!(tsq,-2.0)
@test tsq == t^2

@test log(exp(tsquare)) == tsquare
@test exp(log(1-tsquare)) == 1-tsquare
@test log((1-t)^2) == 2*log(1-t)
Expand Down

0 comments on commit 909689b

Please sign in to comment.