-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
taylor_expand function for Taylor1 and TaylorN #121
Conversation
`taylor_expand(f,x0::Int64)` and `taylor_expand(f,order)` clashed.
I like the idea of this PR, though I am still not sure about the name of the function (and perhaps other things), see below. My proposal here is to twist a little the essence, and address #80. That is, given function update!(x::Taylor1, t0::TaylorSeries.NumberNotSeries)
x.coeffs .= evaluate(x, Taylor1( [t0,one(t0)], x.order ))[:]
return x
end If this works, I guess this could also be extended to Surely, the original idea of this PR is more general, in the sense that it returns the evaluated expansion of a given function The distinction of returning a |
I think the idea above works julia> using TaylorSeries
julia> function update!(x::Taylor1, t0::TaylorSeries.NumberNotSeries)
x.coeffs .= evaluate(x, Taylor1( [t0,one(t0)], x.order ))[:]
return nothing
end
update! (generic function with 1 method)
julia> x = Taylor1([1.0,2.0,3.0])
1.0 + 2.0 t + 3.0 t² + 𝒪(t³)
julia> update!(x, 1.0)
julia> x
6.0 + 8.0 t + 3.0 t² + 𝒪(t³)
julia> update!(x, -1.0)
julia> x
1.0 + 2.0 t + 3.0 t² + 𝒪(t³) |
Incidentally, the fact that tests are not passing may be related to changing the order and the number of variables; see above. |
I think this is a great feature (that I think should be called something like Methods for evaluating
The reason for this was that it took the dimension of the function
Output for travis (both Linux nightly & Mac nightly) is:
I think it has to do to broadcasting as |
I agree that there is a difference between For the tests, I think it's better to check the actual series constructed directly, either using Regarding the |
I was checking this PR, and there is something odd in the many-variable case. For simplicity I will consider two variables. I hope the following comments are helpful. My expectation is that Yet, this is not the case currently. julia> using TaylorSeries
julia> xT, yT = set_variables("x y");
julia> f(x,y) = (x+y)^2
f (generic function with 1 method)
julia> f(xT,yT)
1.0 x² + 2.0 x y + 1.0 y² + 𝒪(‖x‖⁷)
julia> taylor_expand(f, [0.0,0.0])
ERROR: MethodError: no method matching f(::Array{TaylorSeries.TaylorN{Float64},1})
Closest candidates are:
f(::Any, ::Any) at REPL[3]:1
Stacktrace:
[1] #taylor_expand#33(::Int64, ::Function, ::#f, ::Array{Float64,1}) at /Users/benet/.julia/v0.6/TaylorSeries/src/other_functions.jl:146
[2] taylor_expand(::Function, ::Array{Float64,1}) at /Users/benet/.julia/v0.6/TaylorSeries/src/other_functions.jl:143 The error is because in Currently, the function julia> taylor_expand(exp,[0,0.])
...
2-element Array{TaylorSeries.TaylorN{Float64},1}:
1.0 + 1.0 x₁ + 0.5 x₁² + 0.16666666666666666 x₁³ + 0.041666666666666664 x₁⁴ + 0.008333333333333333 x₁⁵ + 0.0013888888888888887 x₁⁶ + 𝒪(‖x‖⁷)
1.0 + 1.0 x₂ + 0.5 x₂² + 0.16666666666666666 x₂³ + 0.041666666666666664 x₂⁴ + 0.008333333333333333 x₂⁵ + 0.0013888888888888887 x₂⁶ + 𝒪(‖x‖⁷) is a vector, and each entry depends only on one of the I think we should consider the function to be defined as in the first example above. Broadcasting ( |
I've covered the case you're telling about @lbenet ! It works as julia> using TaylorSeries
julia> xT, yT = set_variables("x y");
julia> f(x,y) = (x+y)^2
f (generic function with 1 method)
julia> f(xT,yT)
1.0 x² + 2.0 x y + 1.0 y² + 𝒪(‖x‖⁷)
julia> taylor_expand(f, 0.0, 0.0)
1.0 x² + 2.0 x y + 1.0 y² + 𝒪(‖x‖⁷)
julia> @which taylor_expand(f, 0.0, 0.0)
taylor_expand(f::Function, x0...) at .../src/other_functions.jl:152 Additionally,
EDIT 2: Rethinking this issue, I feel that By the way, |
I edited my last comment, @lbenet. I'm not sure if Github notifies this... |
Followed suggestion from @lbenet.
JuliaDiff#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
@blas-ko Can you rebase this branch to current master? This will also restart travis check and then I'll review it. |
`taylor_expand(f,x0::Int64)` and `taylor_expand(f,order)` clashed.
Rebased! (Hope I did it correctly since I don't have experience rebasing yet). |
696c375
to
9cf86ab
Compare
They use set_variables internally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, LGTM. Yet, i have some objection with respect to the use of set_variables
, for which I suggest an alternative. Also I suggest that taylor_expand!
is renamed as update!
(see #80) and is also exported.
Cc: @dpsanders
x0::Array{TaylorN{T},1}) | ||
@assert length(x) == length(x0) | ||
@inbounds for i in eachindex(x) | ||
x0[i] = evaluate( x[i], δx ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps using here (as well in similar occurrences in other methods) evaluate!(x[i], δx, x0[i])
instead, yields better performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed for evaluate
methods but not for evaluate!
methods as evaluate!
, as the docs say, just work for arrays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point!
src/evaluate.jl
Outdated
@assert length(vals) == get_numvars() | ||
|
||
num_vars = get_numvars() | ||
ct = coeff_table |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This creates a copy of coeff_table
. Perhaps using a view
of it, or directly coeff_table
saves this.
I didn't notice this before, sorry, but I think this should also be changed in other occurrences.
src/other_functions.jl
Outdated
|
||
#taylor_expand function for Taylor1 | ||
doc""" | ||
taylor_expand(f,x0;order) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add white spaces? I mean taylor_expand(f, x0; order)
.
As commented below, I am not in favor of changing the number of variables inside the function.
src/other_functions.jl
Outdated
computed, changing the number of `TaylorN` variables | ||
according to the dimension of `f`. | ||
""" | ||
function taylor_expand(f::Function; order::Int64=15) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this will return a Taylor1{Float64}
expansion. My point focuses in the Float64
part.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think taylor_expand(T::Type,f::Function;order::Int64)
is a good idea? In this case, should the same be done when passing an explicit x0
to taylor_expand
?
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that, for Taylor1
expansions it makes sense to allow the user to set the order
of the expansion; I am not in favor of this for TaylorN
expansions, at least as it is now. My objection is related to the use of set_variables
, since it changes some internals, in particular, the maximum order of the TaylorN
expansions. This costs time; also, the idea of the current implementation is to set the parameters related to TaylorN internals only once at the very beginning.
I think this method should assert that the the length of x0
corresponds to get_numvars()
, as you do it, and only when this is fulfilled evaluate f(X .+ x0)
(notice the spaces). In this case, using set_variables
will not change anything internally.
An alternative that avoids using set_variables
is for example:
function taylor_expand{T<:Number}(f::Function, x0::Vector{T}; order::Int64=get_order())
ll = length(x0)
# check that x0 has the correct length and `order` does not exceed the maximum order of the expansions
@assert ll == get_numvars() && order <= get_order()
X = Array{TaylorN{T}}(length(x0)
for i in eachindex(X)
X[i] = TaylorN(T, i, order=order)
end
return f( X .+ x0 )
end
This alternative permits to have expansions of given order
, smaller or equal to get_order()
, e.g., order=2
when get_order()
is 6.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really in favor of this. By the way, really good "type preserving strategy" doing the X[i] = TaylorN(T, i, order)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding the problem with travis in Julia 0.5 (and considering your comment about this), I think a possible solution is to have X
as the shifted vector. I mean, define X[i] = x0[i] + TaylorN(T, i, order=order)
inside the for-loop, and then only return the evaluation of f( X )
. This could be used in each method of taylor_expand
.
I think this could actually solve the problem with travis, and yield a tiny performance improvement, since only one loop would be needed.
src/other_functions.jl
Outdated
function taylor_expand(f::Function, x0...; order::Int64=get_order()) #a Taylor expansion around x0 | ||
ll = length(x0) | ||
ll == get_numvars() ? X = get_variables() : begin | ||
X = set_variables("x",order=order,numvars=ll) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above.
src/other_functions.jl
Outdated
|
||
Takes `a <: Union{Taylo1,TaylorN}` and expands it around the coordinate `x0`. | ||
""" | ||
function taylor_expand!(a::Taylor1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about naming this function update!
(as proposed in #80), and export it? Since this method is some sort of fallback, i think it can be written so a::Union{Taylor1, TaylorN}
, which also covers another method below.
@@ -224,7 +233,6 @@ function evaluate{T<:Number,S<:NumberNotSeries}(a::TaylorN{T}, | |||
suma = Taylor1(zeros(R, ord)) | |||
|
|||
for homPol in 1:length(a) | |||
sun = zero(R) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
Great! I've read all the changes and I'll make them as you propose. I wanted you to see the warning for |
Incidentally, I just noticed this line, which seems to me unnecessary, since there is a method |
I added it in order to keep support for 0.5; once we drop 0.5 support, we can erase this line |
* It doesn't use set_variables() anymore. * typeof(x0) is preserved if possible.
* Added 1 more test...
Seems that for Julia 0.5 broadcasting between
This is, in particular, for line 216 of |
src/other_functions.jl
Outdated
end | ||
|
||
function taylor_expand(f::Function, x0...; order::Int64=get_order()) #a Taylor expansion around x0 | ||
T = eltype(x0[1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since x0
is a tuple, each entry could have a different type. I think that T
should be defined as T = eltype( promote(x0...)[1] )
.
Tests are passing! |
Great! Thanks for all! I'm merging right away! |
This makes reference to #68. A
taylor_expand
function is added forTaylor1
andTaylorN
expansions around aNumber
orVector
, respectively.Obs: The way "common" functions are expanded for arrays such as
taylor_expand(cos.[0.0,1.0])
for julia 0.6 output a warning about a method deprecation for arrays. They suggest to use now the dot operator instead, but this generates some problems with user defined functions.