From b16e006c259bcec0ec1c4c7c935a583bac2db4a0 Mon Sep 17 00:00:00 2001 From: "David P. Sanders" Date: Wed, 22 Jul 2015 12:43:00 -0500 Subject: [PATCH 1/4] Refactor hash tables, fix testsi, clean-up and improvements - Rename generateTables -> generate_tables and refactor to take number of variables and order as arguments - Refactored hash table generation. - Removed explicit tests of hash tables since the exact generation has now changed. - Add blank lines in parameters.jl - Remove unnecessary information from TaylorSeries.jl - Make set_variables accept only strings; fix test - Make index_table an array instead of a dictionary. This significantly improves performance - Fix bug in generate_tables --- src/TaylorSeries.jl | 19 +-------- src/hash_tables.jl | 97 ++++++++++++++++++--------------------------- src/parameters.jl | 10 +++-- test/runtests.jl | 8 ++-- 4 files changed, 51 insertions(+), 83 deletions(-) diff --git a/src/TaylorSeries.jl b/src/TaylorSeries.jl index 89347b8a..cbd52607 100644 --- a/src/TaylorSeries.jl +++ b/src/TaylorSeries.jl @@ -1,27 +1,13 @@ -# TaylorSeries.jl -# -# Julia module for handling Taylor series of arbitrary but finite order -# -# - utils_Taylor1.jl contains the constructors and methods for 1-variable expansions -# -# - utils_TaylorN.jl contains the constructors and methods for N-variable expansions -# -# Last modification: 2015.07.03 -# -# Luis Benet & David P. Sanders -# UNAM -# -# MIT Expat license +# This file is part of the TaylorSeries.jl Julia package, MIT license # +# Handles Taylor series of arbitrary but finite order module TaylorSeries -## Documentation if VERSION < v"0.4.0-dev" using Docile end -## Compatibility v0.3 -> 0.4 using Compat @compat sizehint! @compat trunc @@ -35,7 +21,6 @@ import Base: zero, one, zeros, ones, sqrt, exp, log, sin, cos, tan -## Exported types and methods export Taylor1, TaylorN, HomogeneousPolynomial export taylor1_variable, taylorN_variable, get_coeff, diffTaylor, integTaylor, evaluate, deriv, diff --git a/src/hash_tables.jl b/src/hash_tables.jl index a5e8b285..6548c929 100644 --- a/src/hash_tables.jl +++ b/src/hash_tables.jl @@ -1,86 +1,65 @@ # This file is part of TaylorSeries.jl -# + # Hash tables for HomogeneousPolynomial and TaylorN @doc """ - Generates the array of dictionaries `index_table`, `size_table` and `pos_table`: + Generates the dictionaries `index_table`, `size_table` and `pos_table`: - `index_table`: vector that contains the dictionaries that link the lexicographic position of the monomial with the corresponding indexes of the powers that characterize the monomial of given degree. The vector entry `[k+1]` corresponds to the homogeneous polynomial of degree `k`. + - `size_table`: vector containing the number of distinct monomials of the homogeneous polynomial, ordered by the degree of the polynomial. + - `pos_table`: vector with the inverse of `index_table`, i.e., for a given degree `k` and a vector of indexes (hashed), it returns the (lexicographic) position of the corresponding monomial. """ -> -function generateTables() - maxOrd = get_order() - numVars = get_numvars() - - arrayInd = Array(Dict{Int,Array{Int,1}},maxOrd+1) - arraySize = Array(Int,maxOrd+1) - arrayPos = Array(Dict{UInt,Int},maxOrd+1) - - if numVars==1 - for k = 0:maxOrd - dInd = Dict{Int, Array{Int,1}}() - dPos = Dict{UInt,Int}() - dInd[1] = [k] - dPos[hash([k])] = 1 - arrayInd[k+1] = dInd - arraySize[k+1] = 1 - arrayPos[k+1] = dPos - end - return arrayInd, arraySize, arrayPos + +function generate_tables(num_vars, order) + + index_table = [generate_index_vectors(num_vars, i) for i in 0:order] + + pos_table = map(make_inverse_dict, index_table) + size_table = map(length, index_table) + + index_table, size_table, pos_table + +end + +@doc "Make a list of index vectors with given number of variables and degree" -> +function generate_index_vectors(num_vars, degree) + + if num_vars == 1 + return Vector{Int}[ [degree] ] end - iindices = zeros(Int, numVars) - idic = 0 - for kDeg = 0:maxOrd - pos = 0 - dInd = Dict{Int, Array{Int,1}}() - dPos = Dict{UInt, Int}() - iV = numVars - for iz = 0:kDeg - @inbounds iindices[end] = iz - pos, dInd[pos] = pos2indices!( iindices, pos, dInd, iV, kDeg ) - end - nCoefH = length(dInd) - for i=1:nCoefH - kdic = hash(dInd[i]) - dPos[kdic] = i - end - idic += 1 - arrayInd[idic] = dInd - arraySize[idic] = nCoefH - arrayPos[idic] = dPos + indices = Vector{Int}[] + + for k in degree:-1:0 + + new_indices = [ [k, x...] for x in generate_index_vectors(num_vars-1, degree-k) ] + append!(indices, new_indices) + end - return arrayInd, arraySize, arrayPos + indices + end -function pos2indices!(iIndices::Array{Int,1}, pos::Int, dict::Dict{Int,Array{Int,1}}, - iV::Int, kDeg::Int ) - - jVar = iV-1 - kDegNext = kDeg - iIndices[iV] - if jVar > 1 - for jDeg = 0:kDegNext - @inbounds iIndices[jVar] = jDeg - pos, dict[pos] = pos2indices!( iIndices, pos, dict, jVar, kDegNext ) - end - else - iIndices[1] = kDegNext - pos += 1 - @inbounds dict[pos] = iIndices - end - return pos, iIndices[1:end] +function make_forward_dict(v::Vector) + Dict([i=>x for (i,x) in enumerate(v)]) +end + +function make_inverse_dict(v::Vector) + Dict([hash(x)=>i for (i,x) in enumerate(v)]) end -const index_table, size_table, pos_table = generateTables() + +const index_table, size_table, pos_table = generate_tables(get_numvars(), get_order()) gc(); diff --git a/src/parameters.jl b/src/parameters.jl index 32a6c312..b82baa2c 100644 --- a/src/parameters.jl +++ b/src/parameters.jl @@ -12,6 +12,7 @@ These parameters can be changed using `set_params_TaylorN(order,numVars)` """ -> + type ParamsTaylorN order :: Int num_vars :: Int @@ -36,15 +37,16 @@ end ## Utilities to get the maximum order and number of variables get_order() = _params_TaylorN_.order get_numvars() = _params_TaylorN_.num_vars - get_variable_names() = _params_TaylorN_.variable_names + set_variable_names{T<:String}(names::Vector{T}) = _params_TaylorN_.variable_names = names get_variables() = [taylorN_variable(i) for i in 1:get_numvars()] @doc doc"""`set_variables` sets the names and number of the Taylor variables, as well as the order of the Taylor expansion.""" -> -function set_variables{T}(R::Type, names::Vector{T}; order=6) + +function set_variables{T<:String}(R::Type, names::Vector{T}; order=6) order >= 1 || error("Order must be at least 1") num_vars = length(names) @@ -62,13 +64,14 @@ function set_variables{T}(R::Type, names::Vector{T}; order=6) resize!(size_table,order+1) resize!(pos_table,order+1) - index_table[:], size_table[:], pos_table[:] = generateTables() + index_table[:], size_table[:], pos_table[:] = generate_tables(num_vars, order) gc(); end # return a list of the new variables TaylorN{R}[taylorN_variable(R,i) for i in 1:get_numvars()] end + set_variables{T}(names::Vector{T}; order=6) = set_variables(Float64, names, order=order) function set_variables{T<:String}(R::Type, names::T; order=6, numvars=-1) @@ -81,5 +84,6 @@ function set_variables{T<:String}(R::Type, names::T; order=6, numvars=-1) set_variables(R, variable_names, order=order) end + set_variables{T<:String}(names::T; order=6, numvars=-1) = set_variables(Float64, names, order=order, numvars=numvars) diff --git a/test/runtests.jl b/test/runtests.jl index fedc9c56..a19e88bc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,7 +3,7 @@ using TaylorSeries using FactCheck using Compat -FactCheck.setstyle(:compact) +#FactCheck.setstyle(:compact) # FactCheck.onlystats(true) facts("Tests for Taylor1 expansions") do @@ -118,8 +118,8 @@ facts("Tests for HomogeneousPolynomial and TaylorN") do @fact eltype(set_variables(BigInt, "x y", order=6)) --> TaylorN{BigInt} @fact eltype(set_variables("x y", order=6)) --> TaylorN{Float64} - @fact TaylorSeries.index_table[2][1] == [1,0] --> true - @fact TaylorSeries.pos_table[4][hash([2,1])] == 2 --> true + #@fact TaylorSeries.index_table[2][1] == [1,0] => true + #@fact TaylorSeries.pos_table[4][hash([2,1])] == 2 => true @fact get_order() == 6 --> true @fact get_numvars() == 2 --> true @@ -238,7 +238,7 @@ end facts("Testing an identity proved by Euler (8 variables)") do make_variable(name, index::Int) = string(name, TaylorSeries.subscriptify(index)) - variable_names = [make_variable("α", i) for i in 1:4] + variable_names = UTF8String[make_variable("α", i) for i in 1:4] append!(variable_names, [make_variable("β", i) for i in 1:4]) a1, a2, a3, a4, b1, b2, b3, b4 = set_variables(variable_names, order=4) From 7233fa9ffe69ec6315d6a75703412000867ae4d8 Mon Sep 17 00:00:00 2001 From: "David P. Sanders" Date: Wed, 22 Jul 2015 14:46:02 -0500 Subject: [PATCH 2/4] Clean up TaylorN.jl --- src/TaylorN.jl | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/TaylorN.jl b/src/TaylorN.jl index d6ec08d0..b1a71c9f 100644 --- a/src/TaylorN.jl +++ b/src/TaylorN.jl @@ -1,12 +1,6 @@ -# utils_TaylorN.jl: N-variables Taylor expansions through homogeneous polynomials -# -# Last modification: 2015.07.03 -# -# Luis Benet & David P. Sanders -# UNAM -# -# MIT Expat license -# +# This file is part of TaylorSeries.jl, MIT licensed + +# HomogeneousPolynomial and TaylorN types, and functions defined on them ## Minimum order of a HomogeneousPolynomial compatible with the vector's length From c23f07914a732bfc44ef3023e84842180a099556 Mon Sep 17 00:00:00 2001 From: "David P. Sanders" Date: Thu, 23 Jul 2015 13:31:31 -0500 Subject: [PATCH 3/4] Added two variants to fateman.jl Add check to fateman Refactored fateman --- perf/fateman.jl | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/perf/fateman.jl b/perf/fateman.jl index 6ad75add..26abb838 100644 --- a/perf/fateman.jl +++ b/perf/fateman.jl @@ -1,6 +1,6 @@ using TaylorSeries -set_variables("x", numvars=4, order=40) +x, y, z, w = set_variables(Int128, "x", numvars=4, order=40) function fateman1(degree::Int) T = Int128 @@ -14,10 +14,6 @@ function fateman1(degree::Int) s * ( s+TaylorN(oneH, 2*degree) ) end -f1 = fateman1(0) -println("Fateman 1:") -@time f1 = fateman1(20) - function fateman2(degree::Int) T = Int128 oneH = HomogeneousPolynomial(one(T), 0) @@ -29,6 +25,32 @@ function fateman2(degree::Int) return s^2 + s end -f2 = fateman2(0); -println("Fateman 2:") -@time f2 = fateman2(20); +function fateman3(degree::Int) + s = x + y + z + w + 1 + s = s^degree + s * (s+1) +end + +function fateman4(degree::Int) + s = x + y + z + w + 1 + s = s^degree + s^2 + s +end + +function run_fateman(N) + results = Any[] + + for f in (fateman1, fateman2, fateman3, fateman4) + f(0) + println("Running $f") + @time result = f(N) + push!(results, result) + end + + results +end + + + + +#@show f1==f2==f3==f4 From fffd0f0f5bc84430839a6be7792d7ce5ffb62945 Mon Sep 17 00:00:00 2001 From: "David P. Sanders" Date: Thu, 30 Jul 2015 17:16:35 -0500 Subject: [PATCH 4/4] Use new --> syntax for FactCheck tests Fix Euler test --- test/runtests.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index a19e88bc..6a8da175 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,7 +3,7 @@ using TaylorSeries using FactCheck using Compat -#FactCheck.setstyle(:compact) +FactCheck.setstyle(:compact) # FactCheck.onlystats(true) facts("Tests for Taylor1 expansions") do @@ -118,8 +118,8 @@ facts("Tests for HomogeneousPolynomial and TaylorN") do @fact eltype(set_variables(BigInt, "x y", order=6)) --> TaylorN{BigInt} @fact eltype(set_variables("x y", order=6)) --> TaylorN{Float64} - #@fact TaylorSeries.index_table[2][1] == [1,0] => true - #@fact TaylorSeries.pos_table[4][hash([2,1])] == 2 => true + @fact TaylorSeries.index_table[2][1] == [1,0] --> true + @fact TaylorSeries.pos_table[4][hash([2,1])] == 2 --> true @fact get_order() == 6 --> true @fact get_numvars() == 2 --> true