juliadiff / taylorseries.jl Goto Github PK
View Code? Open in Web Editor NEWTaylor polynomial expansions in one and several independent variables.
License: Other
Taylor polynomial expansions in one and several independent variables.
License: Other
in Taylor1 there is this line
coefhomog += (kcoef-i) * ac[kcoef-i+1] * coeffs[i+1]
which looks for *(::Int64, :::Float64, ::Float64)
It would be more portable to supply the parens
Nemo es a new computer algebra package for Julia. Fateman benchmark with order 30(!):
If one does
julia> using TaylorSeries;
julia> t = Taylor1([1.0,2,3,4,5],2)
1.0 + 2.0 t + 3.0 t² + 4.0 t³ + 5.0 t⁴ + 𝒪(t³)
julia> length(t.coeffs), t.order
(5,2)
notice the 𝒪(t³)
even when there are higher order terms in t
.
This could be treated in two ways:
Taylor1
object into the given order
.Taylor1
object into the lenght of the array of terms.I prefer the first solution because if you explicitly give the order to your polynomial, you would normally want to keep that order always.
Feedback on this issue is welcomed; I can then do a PR based on what's discussed.
These four methods in Taylor1 and in TaylorN, are preventing full BigFloat support. The solution is to promote_type
inside the argument of inv
.
julia> using TaylorSeries
julia> f0,f1,f2,f3,f4,h = set_variables(BigFloat,"f₀ f₁ f₂ f₃ f₄ h",order=5)
6-element Array{TaylorSeries.TaylorN{BigFloat},1}:
1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₀ + 𝒪(‖x‖⁶)
1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₁ + 𝒪(‖x‖⁶)
1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₂ + 𝒪(‖x‖⁶)
1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₃ + 𝒪(‖x‖⁶)
1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₄ + 𝒪(‖x‖⁶)
1.000000000000000000000000000000000000000000000000000000000000000000000000000000 h + 𝒪(‖x‖⁶)
julia> f = Taylor1([f0,f1,f2,f3,f4])
1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₀ + 𝒪(‖x‖⁶) + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₁ + 𝒪(‖x‖⁶) t + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₂ + 𝒪(‖x‖⁶) t² + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₃ + 𝒪(‖x‖⁶) t³ + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₄ + 𝒪(‖x‖⁶) t⁴ + 𝒪(t⁵)
julia> exp(f)
1.000000000000000000000000000000000000000000000000000000000000000000000000000000 + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₀ + 5.000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 f₀² + 1.666666666666666574148081281236954964697360992431640625000000000000000000000000e-01 f₀³ + 4.166666666666666435370203203092387411743402481079101562500000000000000000000000e-02 f₀⁴ + 8.333333333333333333333333333333307654267408170188625920294098867635752825311357e-03 f₀⁵ + 𝒪(‖x‖⁶) + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₁ + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₀ f₁ + 5.000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 f₀² f₁ + 1.666666666666666574148081281236954964697360992431640625000000000000000000000000e-01 f₀³ f₁ + 4.166666666666666435370203203092387411743402481079101562500000000000000000000000e-02 f₀⁴ f₁ + 𝒪(‖x‖⁶) t + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₂ + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₀ f₂ + 5.000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 f₁² + 5.000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 f₀² f₂ + 5.000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 f₀ f₁² + 1.666666666666666574148081281236954964697360992431640625000000000000000000000000e-01 f₀³ f₂ + 2.500000000000000000000000000000000000000000000000000000000000000000000000000000e-01 f₀² f₁² + 4.166666666666666435370203203092387411743402481079101562500000000000000000000000e-02 f₀⁴ f₂ + 8.333333333333332870740406406184774823486804962158203125000000000000000000000000e-02 f₀³ f₁² + 𝒪(‖x‖⁶) t² + 9.999999999999999444888487687421729788184165954589843750000000000000000000000000e-01 f₃ + 9.999999999999999444888487687421729788184165954589843750000000000000000000000000e-01 f₀ f₃ + 9.999999999999999444888487687421729788184165954589843750000000000000000000000000e-01 f₁ f₂ + 4.999999999999999722444243843710864894092082977294921875000000000000000000000000e-01 f₀² f₃ + 9.999999999999999444888487687421729788184165954589843750000000000000000000000000e-01 f₀ f₁ f₂ + 1.666666666666666574148081281236954964697360992431640625000000000000000000000000e-01 f₁³ + 1.666666666666666481629495895807248398541240350825556065941180226472849434937729e-01 f₀³ f₃ + 4.999999999999999722444243843710864894092082977294921875000000000000000000000000e-01 f₀² f₁ f₂ + 1.666666666666666574148081281236954964697360992431640625000000000000000000000000e-01 f₀ f₁³ + 4.166666666666666204073739739518120996353100877063890164852950566182123587344321e-02 f₀⁴ f₃ + 1.666666666666666481629495895807248398541240350825556065941180226472849434937729e-01 f₀³ f₁ f₂ + 8.333333333333332870740406406184774823486804962158203125000000000000000000000000e-02 f₀² f₁³ + 𝒪(‖x‖⁶) t³ + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₄ + 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 f₀ f₄ + 9.999999999999999861222121921855432447046041488647460937500000000000000000000000e-01 f₁ f₃ + 5.000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 f₂² + 5.000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 f₀² f₄ + 9.999999999999999861222121921855432447046041488647460937500000000000000000000000e-01 f₀ f₁ f₃ + 5.000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 f₀ f₂² + 4.999999999999999861222121921855432447046041488647460937500000000000000000000000e-01 f₁² f₂ + 1.666666666666666574148081281236954964697360992431640625000000000000000000000000e-01 f₀³ f₄ + 4.999999999999999930611060960927716223523020744323730468750000000000000000000000e-01 f₀² f₁ f₃ + 2.500000000000000000000000000000000000000000000000000000000000000000000000000000e-01 f₀² f₂² + 4.999999999999999861222121921855432447046041488647460937500000000000000000000000e-01 f₀ f₁² f₂ + 4.166666666666666435370203203092387411743402481079101562500000000000000000000000e-02 f₁⁴ + 4.166666666666666435370203203092387411743402481079101562500000000000000000000000e-02 f₀⁴ f₄ + 1.666666666666666551018434934879528323158330832030119485235295056618212358734432e-01 f₀³ f₁ f₃ + 8.333333333333332870740406406184774823486804962158203125000000000000000000000000e-02 f₀³ f₂² + 2.499999999999999930611060960927716223523020744323730468750000000000000000000000e-01 f₀² f₁² f₂ + 4.166666666666666435370203203092387411743402481079101562500000000000000000000000e-02 f₀ f₁⁴ + 𝒪(‖x‖⁶) t⁴ + 𝒪(t⁵)
It would be useful to have an option to suppress the display of the O(t^4)
term.
Ref http://pkg.julialang.org/detail/TaylorSeries.html, this might be spurious but it surprised me a bit so figured I'd file an issue and let you know. I don't think any of your dependencies have changed versions recently, other than Compat? Would be unfortunate if something changed the meaning of code there.
Related to TaylorIntegration's PR #18. For performance reasons, it would be good to have an in-place evaluation version of jacobian
in TaylorSeries. My proposal is something like this:
function jacobian!{T<:Number}(jjac::Array{T,2}, vf::Array{TaylorN{T},1})
numVars = get_numvars()
@assert length(vf) == numVars
for comp = 1:numVars
jjac[comp,:] = vf[comp].coeffs[2].coeffs[1:end]
end
nothing
end
As far as I've tested it, this change improves memory use on TaylorIntegration Lyapunov spectrum methods, in particular stabilitymatrix!
, where jacobian
is currently used.. Perhaps this could be included in #87 ?
It seems ForwardDiff expects inputs to be <:Real
, but Taylor series is <:Number
. I'm not sure if that's on purpose, so I'm reporting it here.
julia> using TaylorSeries, ForwardDiff
INFO: Recompiling stale cache file /Users/kirill/.julia/lib/v0.6/TaylorSeries.ji for module TaylorSeries.
julia> cos(Taylor1([1.0, 2.0]))
0.5403023058681398 - 1.682941969615793 t + 𝒪(t²)
julia> ForwardDiff.derivative(sin, Taylor1([1.0, 2.0]))
ERROR: MethodError: no method matching derivative(::Base.#sin, ::TaylorSeries.Taylor1{Float64})
Closest candidates are:
derivative(::Any, ::Any, ::Any, ::ForwardDiff.DerivativeConfig) at /Users/kirill/.julia/v0.6/ForwardDiff/src/derivative.jl:7
derivative(::F, ::R<:Real) where {F, R<:Real} at /Users/kirill/.julia/v0.6/ForwardDiff/src/derivative.jl:18
derivative(::F, ::AbstractArray, ::R<:Real) where {F, R<:Real} at /Users/kirill/.julia/v0.6/ForwardDiff/src/derivative.jl:30
...
Changing it to be a subtype of Real seems to work, but I'm not sure if it relies on being Number rather than Real anywhere.
diff --git a/src/constructors.jl b/src/constructors.jl
index c9da264..3ee5dd0 100644
--- a/src/constructors.jl
+++ b/src/constructors.jl
@@ -12,7 +12,7 @@
Parameterized abstract type for [`Taylor1`](@ref),
[`HomogeneousPolynomial`](@ref) and [`TaylorN`](@ref).
"""
-@compat abstract type AbstractSeries{T<:Number} <: Number end
+@compat abstract type AbstractSeries{T<:Number} <: Real end
## Constructors ##
@@ -187,7 +187,7 @@ TaylorN(nv::Int; order::Int=get_order()) = TaylorN(Float64, nv, order=order)
# A `Number` which is not an `AbstractSeries`
-const NumberNotSeries = Union{setdiff(subtypes(Number), [AbstractSeries])...}
+const NumberNotSeries = Union{setdiff(subtypes(Real), [AbstractSeries])...}
# A `Number` which is not a TaylorN nor a HomogeneousPolynomial
const NumberNotSeriesN =
julia> ForwardDiff.derivative(sin, Taylor1([1.0, 2.0]))
0.5403023058681398 - 1.682941969615793 t + 𝒪(t²)
julia> cos(Taylor1([1.0, 2.0]))
0.5403023058681398 - 1.682941969615793 t + 𝒪(t²)
There should be explicit functions for multiplying by constants, since this is very efficient and does not require conversion.
There are a string of conversion errors currently.
It is not clear to me how to represent a Taylor series around a non-zero point
A general interface for multivariate polynomials is being developed:
https://github.com/JuliaAlgebra/MultivariatePolynomials.jl
TaylorSeries.jl should probably implement this interface, and in particular be a subtype of the corresponding abstract type.
Related to #130
Hi all, fairly new Julia user here, and just started trying to use the TaylorSeries package today. I have looked through all the examples I could find online and now am trying to expand a function like this:
f(x,y) = 1 / (x^2 + y^2) about x0=1, y0=1
Based on the examples, here is the code I have tried so far (which isn't giving the correct answer):
~$ julia
_
_ _ ()_ | A fresh approach to technical computing
() | () () | Documentation: https://docs.julialang.org
_ _ | | __ _ | Type "?help" for help.
| | | | | | |/ ` | |
| | || | | | (| | | Version 0.6.0 (2017-06-19 13:05 UTC)
/ |_'|||_'_| | Official http://julialang.org/ release
|__/ | x86_64-apple-darwin13.4.0
julia> using TaylorSeries
julia> x, y = set_variables("x y")
2-element Array{TaylorSeries.TaylorN{Float64},1}:
1.0 x + 𝒪(‖x‖⁷)
1.0 y + 𝒪(‖x‖⁷)
julia> x = x-1
julia> y = y-1
julia> f = (x^2 + y^2)^(-1)
0.5 + 0.5 x + 0.5 y + 0.25 x² + 1.0 x y + 0.25 y² + 1.0 x² y + 1.0 x y² - 0.125 x⁴ + 0.5 x³ y + 1.75 x² y² + 0.5 x y³ - 0.125 y⁴ - 0.125 x⁵ - 0.125 x⁴ y + 1.75 x³ y² + 1.75 x² y³ - 0.125 x y⁴ - 0.125 y⁵ - 0.0625 x⁶ - 0.5 x⁵ y + 0.8125 x⁴ y² + 3.0 x³ y³ + 0.8125 x² y⁴ - 0.5 x y⁵ - 0.0625 y⁶ + 𝒪(‖x‖⁷)
julia> evaluate(f, [1, 1])
14.0
Obviously, I'm expecting a value of 1/2 when I evaluate f = 1 / (1^2 + 1^2) so I know something is wrong here. I've tried a few tweaks to no avail. I'm sure this is either something really simple that I'm doing wrong in the syntax/setup of the problem and would greatly appreciate someone pointing out the correct way to set this up.
julia> s = (x + y)^5
1.0 x⁵ + 5.0 x⁴ y + 10.0 x³ y² + 10.0 x² y³ + 5.0 x y⁴ + 1.0 y⁵ + 𝒪(‖x‖⁷)
julia> s = sin((x + y)^5)
1.0 x⁵ + 5.0 x⁴ y + 10.0 x³ y² + 10.0 x² y³ + 5.0 x y⁴ + 1.0 y⁵ + 𝒪(‖x‖⁷)
Move the index_table
etc. inside the _params_TaylorN_
object (and rename that to _Taylor_params_
)
(Edit: I corrected the expression for sinc(x); the way I originally wrote it was mistaken)
Currently (TaylorSeries v0.3.0.), one can implement
julia> using TaylorSeries #one of the most awesome Julia packages in the world
julia> import Base.sinc #so that we don't overwrite any methods for sinc
julia> sinc{T}(x::Taylor1{T}) = sin(pi*x)/(pi*x) #implementing manually sinc(x)=sin(pi*x)/(pi*x)
sinc (generic function with 7 methods)
julia> x = Taylor1([0.0, 1.0], 16) #a Taylor1 variable
1.0 t + 𝒪(t¹⁷)
julia> sinc(x) #evaluate sinc for a Taylor1 variable
1.0 - 1.6449340668482262 t² + 0.8117424252833536 t⁴ - 0.1907518241220842 t⁶ + 0.026147847817654793 t⁸ - 0.002346081035455823 t¹⁰ + 0.00014842879303107094 t¹² - 6.975873661656378e-6 t¹⁴ + 𝒪(t¹⁷)
But perhaps it would be nice to have this implemented within TaylorSeries without having to do it manually :)
I feel that abs(Taylor)
has a different approach as norm(Taylor,p)
in this Package. abs
here is a function
abs: P → P, where P is a Polynomial
where abs(P) = P
if constant_term(P)
> 0 and abs(P) = -P
if constant_term(P)
< 0
I think norm(Taylor)
should stricly return a non-negative value such that
$$ ||P||p=(sum(k=0)^n|a_k|^p)^(1/p) $$
where ||P||_ ∞ = max_k |a_k|
Right now
using TaylorSeries
X,Y = set_variables("x y");
norm(X-1,2)
1.0 - 1.0 x + 𝒪(‖x‖⁷)
norm(X-1,Inf)
1.0 - 1.0 x + 𝒪(‖x‖⁷)
so I propose extending norm
for Taylors in this way, in a sense we always get a non-negative number as a result.
It should be possible to use TaylorN
also for only 1 variable, shouldn't it? This would simplify the code a lot I think.
Does this give an unacceptable performance hit?
Currently it doesn't work for some reason (with the branch defining set_variables
)
x = set_variables("x")
x + x # works fine
x^2
ERROR: MethodError: `*` has no method matching *(::Array{TaylorSeries.TaylorN{Float64},1}, ::Array{TaylorSeries.TaylorN{Float64},1})
PackageEvaluator.jl is a script that runs nightly. It attempts to load all Julia packages and run their tests (if available) on both the stable version of Julia (0.3) and the nightly build of the unstable version (0.4). The results of this script are used to generate a package listing enhanced with testing results.
Tests pass.
Tests fail, but package loads.
Tests pass.
means that PackageEvaluator found the tests for your package, executed them, and they all passed.
Tests fail, but package loads.
means that PackageEvaluator found the tests for your package, executed them, and they didn't pass. However, trying to load your package with using
worked.
This issue was filed because your testing status became worse. No additional issues will be filed if your package remains in this state, and no issue will be filed if it improves. If you'd like to opt-out of these status-change messages, reply to this message saying you'd like to and @IainNZ will add an exception. If you'd like to discuss PackageEvaluator.jl please file an issue at the repository. For example, your package may be untestable on the test machine due to a dependency - an exception can be added.
Test log:
>>> 'Pkg.add("TaylorSeries")' log
INFO: Installing TaylorSeries v0.0.1
INFO: Package database updated
INFO: METADATA is out-of-date a you may not have the latest version of TaylorSeries
INFO: Use `Pkg.update()` to get the latest versions of your packages
>>> 'using TaylorSeries' log
WARNING: deprecated syntax "{}" at /home/idunning/pkgtest/.julia/v0.4/TaylorSeries/src/TaylorSeries.jl:61.
Use "[]" instead.
Julia Version 0.4.0-dev+2997
Commit e41a507 (2015-01-30 05:35 UTC)
Platform Info:
System: Linux (x86_64-unknown-linux-gnu)
CPU: Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Sandybridge)
LAPACK: libopenblas
LIBM: libopenlibm
LLVM: libLLVM-3.3
>>> test log
WARNING: deprecated syntax "{}" at /home/idunning/pkgtest/.julia/v0.4/TaylorSeries/src/TaylorSeries.jl:61.
Use "[]" instead.
WARNING: itrunc(x) is deprecated, use trunc(Integer,x) instead.
in depwarn at ./deprecated.jl:40
in itrunc at deprecated.jl:29
in ^ at /home/idunning/pkgtest/.julia/v0.4/TaylorSeries/src/utils_Taylor1.jl:207
in anonymous at test.jl:87
in do_test at test.jl:47
in include at ./boot.jl:249
in include_from_node1 at loading.jl:128
in process_options at ./client.jl:319
in _start at ./client.jl:403
ERROR: LoadError: test failed: (2.718281828459045 == e = 2.7182818284590...)
in expression: evalTaylor(exp(Taylor([0,1],17)),1.0) == e
in error at error.jl:19
in default_handler at test.jl:27
in do_test at test.jl:50
in include at ./boot.jl:249
in include_from_node1 at loading.jl:128
in process_options at ./client.jl:319
in _start at ./client.jl:403
while loading /home/idunning/pkgtest/.julia/v0.4/TaylorSeries/test/runtests.jl, in expression starting on line 69
INFO: Testing TaylorSeries
============================[ ERROR: TaylorSeries ]=============================
failed process: Process(`/home/idunning/julia04/usr/bin/julia --check-bounds=yes --code-coverage=none --color=no /home/idunning/pkgtest/.julia/v0.4/TaylorSeries/test/runtests.jl`, ProcessExited(1)) [1]
================================================================================
INFO: No packages to install, update or remove
ERROR: TaylorSeries had test errors
in error at error.jl:19
in test at pkg/entry.jl:717
in anonymous at pkg/dir.jl:28
in cd at ./file.jl:20
in cd at pkg/dir.jl:28
in test at pkg.jl:68
in process_options at ./client.jl:241
in _start at ./client.jl:403
>>> end of log
On Julia 0.5.1, along with TaylorSeries latest master:
julia> using TaylorSeries
julia> x = Taylor1(rand(5), 4)
0.8184698412499662 + 0.6126746629610416 t + 0.7501066040877835 t² + 0.9805243808760169 t³ + 0.8398636369337393 t⁴ + 𝒪(t⁵)
julia> x[1]
0.8184698412499662
julia> x[end]
0.8398636369337393
julia> x[1:end]
5-element Array{Float64,1}:
0.81847
0.612675
0.750107
0.980524
0.839864
works fine, but:
julia> x[:]
ERROR: MethodError: no method matching getindex(::TaylorSeries.Taylor1{Float64}, ::Colon)
julia> x[:] = rand(5)
ERROR: MethodError: no method matching setindex!(::TaylorSeries.Taylor1{Float64}, ::Array{Float64,1}, ::Colon)
gives an error. A workaround is to simply use .coeffs
:
julia> x.coeffs[:]
5-element Array{Float64,1}:
0.81847
0.612675
0.750107
0.980524
0.839864
julia> x.coeffs[:] = rand(5)
5-element Array{Float64,1}:
0.0665044
0.0664276
0.341507
0.646912
0.811692
but I think it would be nice to have getindex
and setindex!
methods using ::Colon
... what do you guys think @lbenet @dpsanders ?
I was thinking of implementing a function so it expands an independent variable of a given order around a function f
? This could be something like
function expand(f::Function,order::Int64=15)
a = Taylor1(order)
return f(a)
end
I don't know if it's very efficient because the function doesn't know a priori the output's type, but I think it's practical for TaylorSeries
users.
TaylorRec{T,N}
is an implementation of multivariate Taylor polynomials as a recursive dense representation, including tests. It is in the "TaylorRec" branch.
The idea is to generate a polynomial in N variables as a polynomial of one variable, with coefficients that are polynomials in N-1 variables. For the time being, it is incorporated along TaylorSeries, i.e., without any replacement. It seems to be much slower, probably due to the bad memory management that the recursion imposes.
@dpsanders I think this is partially what you had in mind in #11, avoiding the problem I described there. There are some nice things of this approach; yet, the performance is bad...
We should make N
a type parameter, so that Taylor1
produces an object of type Taylor{1}
, and TaylorN
an object of type Taylor{N}
, where N
is the number of variables.
I'm working with Taylor1{TaylorN{Float64}}
variables in Julia 0.5 using TaylorSeries latest master, but are having some trouble with two cases for the division:
Taylor1{TaylorN{Float64}}
'sTaylor1{TaylorN{Float64}}
by a Float64
julia> using TaylorSeries
julia> x = 1.0 + TaylorN(Float64,1,order=5)
1.0 + 1.0 x₁ + 𝒪(‖x‖⁶)
julia> y = Taylor1(x, 16)
1.0 + 1.0 x₁ + 𝒪(‖x‖⁶) + 𝒪(t¹⁷)
julia> y/y # division of Taylor1{TaylorN{Float64}}'s
ERROR: MethodError: no method matching isinf(::TaylorSeries.TaylorN{Float64})
Closest candidates are:
isinf(::BigFloat) at mpfr.jl:792
isinf(::Float16) at float16.jl:118
isinf(::Real) at float.jl:362
...
in divfactorization(::TaylorSeries.Taylor1{TaylorSeries.TaylorN{Float64}}, ::TaylorSeries.Taylor1{TaylorSeries.TaylorN{Float64}}) at /Users/Jorge/.julia/v0.5/TaylorSeries/src/arithmetic.jl:430
in /(::TaylorSeries.Taylor1{TaylorSeries.TaylorN{Float64}}, ::TaylorSeries.Taylor1{TaylorSeries.TaylorN{Float64}}) at /Users/Jorge/.julia/v0.5/TaylorSeries/src/arithmetic.jl:382
julia> y/1.0 # divide a Taylor1{TaylorN{Float64}} by a Float64
Segmentation fault: 11
It seems that in order to properly define division of two Taylor1{TaylorN{Float64}}
's, either a method isinf(::TaylorSeries.TaylorN{Float64})
or divfactorization{T<:Real}(a1::Taylor1{TaylorN{T}}, b1::Taylor1{TaylorN{T}})
must be defined. Also, in order to define the division of a Taylor1{TaylorN{Float64}}
by a Float64
, a specialized method /{T<:Real}(a::Taylor1{TaylorN{T}}, b::T)
must be defined. Currently, what I'm doing to work around this is:
using TaylorSeries
import Base./
#specialized method of /
/{T<:Real}(a::Taylor1{TaylorN{T}}, b::T) = a * inv(b)
import TaylorSeries.divfactorization
#unsafe, provisional specialized method of divfactorization
#in order to work, isnan, isinf must be defined for TaylorN's
#modified from the currently implemented method in TaylorSeries
function divfactorization{T<:Real}(a1::Taylor1{TaylorN{T}}, b1::Taylor1{TaylorN{T}})
# order of first factorized term; a1 and b1 assumed to be of the same order
a1nz = TaylorSeries.findfirst(a1)
b1nz = TaylorSeries.findfirst(b1)
orddivfact = min(a1nz, b1nz)
if orddivfact < 0
orddivfact = a1.order
end
cdivfact = a1.coeffs[orddivfact+1] / b1.coeffs[orddivfact+1]
return orddivfact, cdivfact
end
And then (although the divfactorization
method lacks some checks), everything works smoothly:
julia> x = 1.0 + TaylorN(Float64,1,order=5)
1.0 + 1.0 x₁ + 𝒪(‖x‖⁶)
julia> y = Taylor1(x, 16)
1.0 + 1.0 x₁ + 𝒪(‖x‖⁶) + 𝒪(t¹⁷)
julia> y/1.0
1.0 + 1.0 x₁ + 𝒪(‖x‖⁶) + 𝒪(t¹⁷)
julia> y/y
1.0 + 𝒪(‖x‖⁶) + 𝒪(t¹⁷)
With this workaround, some more elaborate cases work. As stated above, it seems that the division of two Taylor1{TaylorN{Float64}}
's may also be fixed by defining isinf(::TaylorSeries.TaylorN{Float64})
.
It hasn't been formally announced, but we are building up an organization for differentiation tools called JuliaDiff: http://www.juliadiff.org/. This package seems like a good fit, so let me know if you're interested in moving it into the organization.
There is some minor problem with the way BigFloat's are handled:
julia> promote_type(BigFloat, Taylor1{BigFloat})
ERROR: StackOverflowError:
Stacktrace:
[1] promote_type(::Type{BigFloat}, ::Type{TaylorSeries.Taylor1{BigFloat}}) at ./promotion.jl:161 (repeats 80000 times)
julia> promote_type(Float64, Taylor1{Float64})
TaylorSeries.Taylor1{Float64}
Based on offline discussions with @lbenet and @PerezHz (Jet Transport performance is amazing compared with TaylorN) I've been sketching some ideas for having a nested Taylor1 object working as a N-variable Taylor expansion (some of this have been worked around in #12).
This would address some of the TaylorN issues ( #24 , #11 , etc ) and would make an N-variable expansion much similar (in construction) to a 1-variable expansion. The only main difference would be about complexity and maybe the way of storing/printing coefficients.
One of the first results I found is that, if a Taylor1 operation has a complexity of, say, M, then the same nested Taylor1 object equivalent to an N-variable expansion would be of complexity M^N (N times the operations of a Taylor1 object), which is nasty. On the other hand, this would allocate really little memory, as there wouldn't be any need to call for special dictionaries or so.
I've not thought yet of a way to reduce this complexity, but I don't know about the actual complexity for the current TaylorN either.
Discussion about this would be appreciated.
cc: @dpsanders
As reported in #92, arithmetic operations are subtle when dealing with Taylor1{TaylorN{T}}
. The simplest case I've come to, which yields to a segmentation fault is:
julia> using TaylorSeries
julia> x = 1.0 + TaylorN(Float64,1,order=5)
1.0 + 1.0 x₁ + 𝒪(‖x‖⁶)
julia> y = Taylor1(x, 16)
1.0 + 1.0 x₁ + 𝒪(‖x‖⁶) + 𝒪(t¹⁷)
julia> x + y
The problem seems to be related with promotion.
R. P. Brent and H. T. Kung. Fast Algorithms for Manipulating Formal Power Series. Journal of the ACM, 25(4):581–595, 1978.
The Polynomials.jl
package starts indexing at 0
, so that p[0]
is the 0th order term, p[1]
is the first-order term, etc. (see below).
I suggest changing to this behaviour.
julia> using Polynomials
julia> p = Poly([1, 2, 3])
Poly(1 + 2*x + 3*x^2)
julia> p[0]
1
julia> p[1]
2
julia> p[2]
3
julia> p[3]
0
I just noticed that tests are not passing for v0.2.0 of TaylorSeries.jl
on Julia v0.4, when they actually did; something alike is happening in v0.1.2 with Julia v0.3.
The following is taken from these logs:
Julia v0.3
2016-06-17 to 2016-06-26, v0.1.2, Tests fail.
2016-05-08 to 2016-06-16, v0.1.2, Tests pass.
...
Julia v0.4
2016-06-26 to 2016-06-26, v0.2.0, Tests fail.
2016-06-22 to 2016-06-25, v0.2.0, Tests pass.
...
I have no clue what might have happened.
CC: @tkelman
While working with TaylorIntegration.jl and TaylorSeries.jl, I came across a notable slowdown after PR #99. While benchmarking TaylorIntegration.jl tests using commit 3a8e12e in PerezHz/TaylorIntegration.jl#18 in julia 0.6.0-pre.alpha.315 I got the following typical values (as always, I ran a "warmup lap" before benchmarking to discard compilation overhead):
Julia 0.6.0-pre.alpha.315 TaylorIntegration.jl tests benchmarks for different commits of TaylorSeries:
TaylorSeries latest master (commit 47b201c, PR #101):
22.468 seconds (124.61 M allocations: 19.621 GiB)
TaylorSeries commit 0697deb (PR #99):
22.786 seconds (124.60 M allocations: 20.336 GiB, 15.47% gc time)
TaylorSeries commit 487cb8b (PR #97):
16.958 seconds (112.10 M allocations: 10.923 GiB, 14.04% gc time)
So there's a slowndown of about 30% in typical execution times, about 11% more allocations, and about 50% more total bytes allocated when using commits 47b201c and 0697deb vs using commit 487cb8b in julia 0.6.0-pre.alpha. I also tested some "heavier" benchmarks on two different machines, for a more complicated problem than the ones included in TaylorIntegration.jl's tests, and the slowdown is even bigger, about 50%.
Interestingly enough, this slowdown does not occur in julia 0.5.1. Still, julia-0.5.1 fastest time is slower than julia-0.6.0-pre.alpha slowest time:
Julia 0.5.1 TaylorIntegration.jl tests benchmarks for different commits of TaylorSeries:
There doesn't seem to be "partial integration" of a Taylor series with respect to a single variable.
For example, if we have
f(a, t) = a + a*t
we should be able to integrate with respect to t
in the interval [0, τ]
Hi
Often when I work with TaylorSeries, I need to update the coefficients of a TaylorSeries around a next point.
A very convenient feature would be an update! function.
Example:
x = Taylor1([1.0, 2.0, 3.0])
update!(x, 1.0)
where the result would give for x
6+8t+3t^2+O(t^3)
As a workaround I am using for the moment
t = Taylor1[1.0, 1.0]
x = evaluate(x, t)
Looking at the code some optimization in update! is possible. A generalized Horner procedure can do this efficiently. If there is some interest, I will post tomorrow a possible implementation.
Hi! I was reading the Function-like objects section of the Julia language documentation, and also @dpsanders's recent blog post, and thought that perhaps it would be nice to add function-like behavior for Taylor1, TaylorN and HomogeneousPolynomial variables? My idea is to implement something like:
julia> using TaylorSeries
julia> t = Taylor1(16)
1.0 t + 𝒪(t¹⁷)
julia> p = sin(t)
1.0 t - 0.16666666666666666 t³ + 0.008333333333333333 t⁵ - 0.0001984126984126984 t⁷ + 2.7557319223985893e-6 t⁹ - 2.505210838544172e-8 t¹¹ + 1.6059043836821616e-10 t¹³ - 7.647163731819817e-13 t¹⁵ + 𝒪(t¹⁷)
julia> p(0.1)
ERROR: MethodError: objects of type TaylorSeries.Taylor1{Float64} are not callable
julia> (p::Taylor1)(x) = evaluate(p, x)
julia> p(0.1)
0.09983341664682815
julia> sin(0.1) #just comparing last answer to the actual result of evaluating sin at 0.1
0.09983341664682815
And similar stuff for HomogeneousPolynomials and TaylorNs... If you think this is a worthwhile feature to add to TaylorSeries
, I'd be more than happy to submit a PR! 😄
Perhaps a simpler solution for the fixorder
part of #95 is to define getindex
for a Taylor1
as
julia v0.5> Base.getindex(t::Taylor1, i::Integer) = i <= length(t.coeffs) ? t.coeffs[i] : zero(eltype(t))
the second package to find order dependance
I had the same problem many months ago. Seeing Mike's note allowed me to inform you of that.
Was just doing some work on my machine with TaylorN (OS X 10.10.5, julia-0.5; TaylorSeries v0.4.0), and then I came across some unexpected behaviour:
julia> using TaylorSeries
julia> δv = set_variables("δ", order=1, numvars=65);
julia> (1+δv[1])^2
1.0 + 2.0 δ₁ + 𝒪(‖x‖²) #this is OK
julia> δv = set_variables("δ", order=1, numvars=66);
julia> (1+δv[1])^2
1.0 + 2.0 δ₂ + 𝒪(‖x‖²) #the subscript on the δ should be 1 instead of 2
julia> δv = set_variables("δ", order=1, numvars=70);
julia> (1+δv[1])^2
1.0 + 2.0 δ₆ + 𝒪(‖x‖²) #the subscript on the δ should be 1 instead of 6
julia> δv = set_variables("δ", order=1, numvars=5);
julia> (1+δv[1])^2
1.0 + 2.0 δ₁ + 𝒪(‖x‖²) #this is OK
julia> δv = set_variables("δ", order=1, numvars=65);
julia> (1+δv[1])^2
1.0 + 2.0 δ₁ + 𝒪(‖x‖²) #this is OK
There seems to be a problem with TaylorN
when order==1
and numvars>65
...
If I use order=2
instead of order=1
, everything works fine (this is the workaround I'm using):
julia> δv = set_variables("δ", order=2, numvars=65);
julia> (1+δv[1])^2
1.0 + 2.0 δ₁ + 1.0 δ₁² + 𝒪(‖x‖³) #OK
julia> δv = set_variables("δ", order=2, numvars=66);
julia> (1+δv[1])^2
1.0 + 2.0 δ₁ + 1.0 δ₁² + 𝒪(‖x‖³) #OK
julia> δv = set_variables("δ", order=2, numvars=70);
julia> (1+δv[1])^2
1.0 + 2.0 δ₁ + 1.0 δ₁² + 𝒪(‖x‖³) #OK
julia> δv = set_variables("δ", order=2, numvars=5);
julia> (1+δv[1])^2
1.0 + 2.0 δ₁ + 1.0 δ₁² + 𝒪(‖x‖³) #OK
julia> δv = set_variables("δ", order=2, numvars=65);
julia> (1+δv[1])^2
1.0 + 2.0 δ₁ + 1.0 δ₁² + 𝒪(‖x‖³) #OK
After testing in JuliaBox (julia-0.5, TaylorSeries v0.4.0) the results are the same...
So, I define:
using TaylorSeries
t = Taylor1([0,1//1],5)
#Out: 1//1 t + 𝒪(t⁶)
t^2
#Out: 1//1 t^2 + 𝒪(t⁶)
# which works for squaring t
exp(t)
#Out: 1.0 + 1.0 t + 0.5 t² + 0.16666666666666666 t³ + 0.041666666666666664 t⁴ + 0.008333333333333333 t⁵ + 𝒪(t⁶)
# which isn't what would I would expect
I would expect
exp(t)
#Out: 1//1 + 1//1 t + 1//2 t² + 1//6 t³ + 1//24 t⁴ + 1//120 t⁵ + 𝒪(t⁶)
I know I could use convert(Taylor1{Rational{Int64}},exp(t))
, but it's unconfortable.
julia> t = Taylor1(10)
1.0 t + 𝒪(t¹¹)
julia> sqrt(t^2 + t^3)
1.0 t + 0.5 t² - 0.125 t³ + 0.0625 t⁴ - 0.0390625 t⁵ + 0.02734375 t⁶ - 0.0205078125 t⁷ + 0.01611328125 t⁸ + 𝒪(t¹¹)
This seems to imply that the t^9 and t^10 terms have zero coefficients, which is incorrect.
I think we should tag at least a new patch version.
While working on PR #118 (see also discussion in #116), I was thinking that perhaps it'd be nice to have defined evaluate{T<:NumberNotSeries}(a::TaylorN{T}, vals::Array{TaylorN{T},1})
, or something similar, in order to be able to compose Taylor expansions of N-variable functions. There is already a similar method for Taylor1
, which allows to evaluate a Taylor1
on a Taylor1
.
What I'm trying to say (using syntax from #118) is that whereas it is possible to compose two Taylor1
s,
julia> using TaylorSeries
julia> t = Taylor1(25)
1.0 t + 𝒪(t²⁶)
julia> p = sin(t)
1.0 t - 0.16666666666666666 t³ + 0.008333333333333333 t⁵ - 0.0001984126984126984 t⁷ + 2.7557319223985893e-6 t⁹ - 2.505210838544172e-8 t¹¹ + 1.6059043836821616e-10 t¹³ - 7.647163731819817e-13 t¹⁵ + 2.811457254345521e-15 t¹⁷ - 8.220635246624331e-18 t¹⁹ + 1.9572941063391263e-20 t²¹ - 3.868170170630684e-23 t²³ + 6.446950284384474e-26 t²⁵ + 𝒪(t²⁶)
julia> q = cos(t)
1.0 - 0.5 t² + 0.041666666666666664 t⁴ - 0.001388888888888889 t⁶ + 2.48015873015873e-5 t⁸ - 2.7557319223985894e-7 t¹⁰ + 2.08767569878681e-9 t¹² - 1.1470745597729726e-11 t¹⁴ + 4.779477332387386e-14 t¹⁶ - 1.5619206968586228e-16 t¹⁸ + 4.1103176233121653e-19 t²⁰ - 8.896791392450574e-22 t²² + 1.6117375710961184e-24 t²⁴ + 𝒪(t²⁶)
julia> p(q) #evaluate a Taylor1 on a Taylor1; compare with: sc = x->sin(cos(x)); sc(t)
0.8414709848078965 - 0.2701511529340699 t² - 0.08267127702314792 t⁴ + 0.028036523686489453 t⁶ - 0.0019241418790800983 t⁸ - 0.0004838563431246892 t¹⁰ + 0.00013040017931079692 t¹² - 1.210231179202225e-5 t¹⁴ - 3.316644672471871e-7 t¹⁶ + 2.429814411744226e-7 t¹⁸ - 3.288747013801372e-8 t²⁰ + 1.8233411897292427e-9 t²² + 1.2200826998513497e-10 t²⁴ + 𝒪(t²⁶)
julia> [p, q]([q, p]) #evaluate an array of Taylor1s on an array of Taylor1s
2-element Array{TaylorSeries.Taylor1{Float64},1}:
0.8414709848078965 - 0.2701511529340699 t² - 0.08267127702314792 t⁴ + 0.028036523686489453 t⁶ - 0.0019241418790800983 t⁸ - 0.0004838563431246892 t¹⁰ + 0.00013040017931079692 t¹² - 1.210231179202225e-5 t¹⁴ - 3.316644672471871e-7 t¹⁶ + 2.429814411744226e-7 t¹⁸ - 3.288747013801372e-8 t²⁰ + 1.8233411897292427e-9 t²² + 1.2200826998513497e-10 t²⁴ + 𝒪(t²⁶)
1.0 - 0.5 t² + 0.20833333333333331 t⁴ - 0.05138888888888889 t⁶ + 0.011334325396825395 t⁸ - 0.0022511574074074074 t¹⁰ + 0.00039391308922558923 t¹² - 6.30631883732082e-5 t¹⁴ + 9.459548466503244e-6 t¹⁶ - 1.3341203587285381e-6 t¹⁸ + 1.777225182337089e-7 t²⁰ - 2.2544681245974032e-8 t²² + 2.739783349785652e-9 t²⁴ + 𝒪(t²⁶)
analogous things cannot currently be done for TaylorN
s:
julia> using TaylorSeries
julia> dx = set_variables("x", numvars=4, order=10);
julia> v = [1.0,2,3,4];
julia> dx[1](v) #TaylorN evaluated at a Vector{Float64}
1.0
julia> dx(v) #Vector{TaylorN} evaluated at a Vector{Float64}
4-element Array{Float64,1}:
1.0
2.0
3.0
4.0
julia> dx[1](dx)#TaylorN evaluated at a Vector{TaylorN}
ERROR: MethodError: no method matching evaluate(::TaylorSeries.TaylorN{Float64}, ::Array{TaylorSeries.TaylorN{Float64},1})
Closest candidates are:
evaluate(::TaylorSeries.TaylorN{T<:Number}) where T<:Number at /Users/Jorge/forks/TaylorSeries.jl/src/evaluate.jl:211
evaluate(::TaylorSeries.TaylorN{T<:Number}, ::Array{S<:Union{Complex, Real},1}) where {T<:Number, S<:Union{Complex, Real}} at /Users/Jorge/forks/TaylorSeries.jl/src/evaluate.jl:164
evaluate(::TaylorSeries.TaylorN{T<:Number}, ::Array{TaylorSeries.Taylor1{S<:Union{Complex, Real}},1}) where {T<:Number, S<:Union{Complex, Real}} at /Users/Jorge/forks/TaylorSeries.jl/src/evaluate.jl:188
...
Stacktrace:
[1] (::TaylorSeries.TaylorN{Float64})(::Array{TaylorSeries.TaylorN{Float64},1}) at /Users/Jorge/forks/TaylorSeries.jl/src/evaluate.jl:229
julia> dx(dx) #Vector{TaylorN} evaluated at a Vector{TaylorN}
ERROR: MethodError: no method matching evaluate(::Array{TaylorSeries.TaylorN{Float64},1}, ::Array{TaylorSeries.TaylorN{Float64},1})
Closest candidates are:
evaluate(::Array{TaylorSeries.TaylorN{T<:Union{Complex, Real}},1}, ::Array{S<:Union{Complex, Real},1}) where {T<:Union{Complex, Real}, S<:Union{Complex, Real}} at /Users/Jorge/forks/TaylorSeries.jl/src/evaluate.jl:220
evaluate(::Array{TaylorSeries.TaylorN{T<:Number},1}) where T<:Number at /Users/Jorge/forks/TaylorSeries.jl/src/evaluate.jl:226
evaluate(::Array{TaylorSeries.TaylorN{T<:Number},1}, ::Array{T<:Number,1}) where T<:Number at /Users/Jorge/forks/TaylorSeries.jl/src/evaluate.jl:214
Stacktrace:
[1] (::Array{TaylorSeries.TaylorN{Float64},1})(::Array{TaylorSeries.TaylorN{Float64},1}) at /Users/Jorge/forks/TaylorSeries.jl/src/evaluate.jl:234
I have some ideas on this that actually I was already testing while working on #118, so if there's interest I can submit a PR!
Can we get the following to produce rational coefficients for sin.
julia> t = taylor1_variable(Rational{Int}, 10)
1//1 t + 𝒪(t¹¹)
julia> sin(t)
1.0 t - 0.16666666666666666 t³ + 0.008333333333333333 t⁵ - 0.0001984126984126984 t⁷ + 2.7557319223985893e-6 t⁹ + 𝒪(t¹¹)
The following seems wrong:
julia> Taylor1(Float64, 0)
1.0 t + 𝒪(t²)
I think the following should throw an error instead.
julia> x, y = set_variables("x y", order=8)
2-element Array{TaylorSeries.TaylorN{Float64},1}:
1.0 x + 𝒪(‖x‖⁹)
1.0 y + 𝒪(‖x‖⁹)
julia> sqrt(x)
Inf x - NaN y - Inf x² - NaN x y - NaN y² + Inf x³ - NaN x² y - NaN x y² - NaN y³ - Inf x⁴ - NaN x³ y - NaN x² y² - NaN x y³ - NaN y⁴ + Inf x⁵ - NaN x⁴ y - NaN x³ y² - NaN x² y³ - NaN x y⁴ - NaN y⁵ - Inf x⁶ - NaN x⁵ y - NaN x⁴ y² - NaN x³ y³ - NaN x² y⁴ - NaN x y⁵ - NaN y⁶ + Inf x⁷ - NaN x⁶ y - NaN x⁵ y² - NaN x⁴ y³ - NaN x³ y⁴ - NaN x² y⁵ - NaN x y⁶ - NaN y⁷ - Inf x⁸ - NaN x⁷ y - NaN x⁶ y² - NaN x⁵ y³ - NaN x⁴ y⁴ - NaN x³ y⁵ - NaN x² y⁶ - NaN x y⁷ - NaN y⁸ + 𝒪(‖x‖⁹)
Part of the current slowness is due to creating lots of HomogeneousPolynomial
objects, namely each time a multiplication occurs.
It should be faster to go back to the original idea of having TaylorSeries
be a single block of coefficients, but still treat them as blocks belonging to individual homogeneous polynomials, and not create new arrays of coefficients, but just create a single new TaylorSeries object, and write the calculated coefficients straight into that object.
In the User guide.ipynb the function evalTaylor
is suggested but instead evaluate
is used. It is critical in the KeplerProblem.ipynb example where evalTaylor
is inside the function TaylorStepper but it is not defined in the source files anymore.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.