Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9199067
first version for multivariate functions of type trivialtensorizer
benjione Sep 1, 2022
4e6a8ab
performance improvements
benjione Sep 5, 2022
00c8118
added simple test cases
benjione Sep 5, 2022
bb0f8f6
fix test and extension
benjione Sep 5, 2022
2758897
comment broken test out for old Julia versions
benjione Sep 8, 2022
568c3f5
fixed ordering of tensorization
benjione Sep 8, 2022
00d75e3
simd change and vector type
benjione Sep 12, 2022
a821c96
small changes
benjione Sep 15, 2022
9263003
enabled broken test
benjione Sep 15, 2022
03e123a
u
benjione Oct 12, 2022
2f23248
fixed unbound parameters
benjione Oct 12, 2022
775ace3
type fix
benjione Oct 12, 2022
64c9b54
Merge branch 'master' of github.com:JuliaApproximation/ApproxFunBase.jl
benjione Oct 17, 2022
2d61874
type fixes
benjione Oct 17, 2022
2cfe115
add Polynomials for testing in Project toml
benjione Oct 18, 2022
e9a0032
Merge branch 'JuliaApproximation:master' into master
benjione Nov 16, 2022
236eab4
invoked 2D case
benjione Nov 17, 2022
98eaa53
move multivariate tests to orthogonal polynomial repository
benjione Nov 17, 2022
c9430a8
Merge branch 'master' of github.com:benjione/ApproxFunBase.jl
benjione Nov 17, 2022
f25efa7
Merge branch 'JuliaApproximation:master' into master
benjione Nov 17, 2022
2033c82
delete multivariate
benjione Nov 17, 2022
effb5a4
Merge branch 'master' of github.com:benjione/ApproxFunBase.jl
benjione Nov 17, 2022
582c232
Merge branch 'master' into master
jishnub Nov 19, 2022
5adac34
fixed block type and rewritten trivialtensor iterator
benjione Nov 19, 2022
d08dcb8
Merge branch 'master' of github.com:benjione/ApproxFunBase.jl
benjione Nov 19, 2022
dd3cb6b
remove Orthogonal polynomials from Project toml
benjione Nov 19, 2022
d7313fc
adding TensorIteratorFun
benjione Nov 21, 2022
e1fb701
changed project toml
benjione Nov 21, 2022
6640875
rename TrivialTensorFun and add check if all spaces in Tensorspace ar…
benjione Nov 21, 2022
656a717
performance optimization
benjione Nov 21, 2022
36d9411
added ProductFun which is not working as a comment
benjione Nov 23, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ BandedMatrices = "aae01518-5342-5314-be14-df237901396f"
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0"
Calculus = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
DSP = "717857b8-e6f2-59f4-9121-6e50c889abd2"
DomainSets = "5b8099bc-c8ec-5219-889f-1d9e522a28bf"
DualNumbers = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"
Expand All @@ -32,6 +33,7 @@ BandedMatrices = "0.16, 0.17"
BlockArrays = "0.14, 0.15, 0.16"
BlockBandedMatrices = "0.10, 0.11"
Calculus = "0.5"
Combinatorics = "1.0.2"
DSP = "0.6, 0.7"
DomainSets = "0.5"
DualNumbers = "0.6.2"
Expand Down
2 changes: 2 additions & 0 deletions src/ApproxFunBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import Base.Broadcast: BroadcastStyle, Broadcasted, AbstractArrayStyle,

import Statistics: mean

import Combinatorics: multiexponents

import LinearAlgebra: BlasInt, BlasFloat, norm, ldiv!, mul!, det, cross,
qr, qr!, rank, isdiag, istril, istriu, issymmetric,
Tridiagonal, diagm, diagm_container, factorize,
Expand Down
1 change: 1 addition & 0 deletions src/Multivariate/Multivariate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ include("VectorFun.jl")
include("TensorSpace.jl")
include("LowRankFun.jl")
include("ProductFun.jl")
include("TrivialTensorFun.jl")


arglength(f)=length(Base.uncompressed_ast(f.code.def).args[1])
Expand Down
7 changes: 5 additions & 2 deletions src/Multivariate/ProductFun.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

export ProductFun


"""
ProductFun(f, space::TensorSpace; [tol=eps()])

Expand All @@ -28,6 +29,7 @@ julia> coefficients(P) # power only at the (1,1) Chebyshev mode
0.0 1.0
```
"""

struct ProductFun{S<:UnivariateSpace,V<:UnivariateSpace,SS<:AbstractProductSpace,T} <: BivariateFun{T}
coefficients::Vector{VFun{S,T}} # coefficients are in x
space::SS
Expand Down Expand Up @@ -241,7 +243,8 @@ function coefficients(f::ProductFun,ox::Space,oy::Space)
end

(f::ProductFun)(x,y) = evaluate(f,x,y)
(f::ProductFun)(x,y,z) = evaluate(f,x,y,z)
# ProductFun does only support BivariateFunctions, this function below just does not work
# (f::ProductFun)(x,y,z) = evaluate(f,x,y,z)

coefficients(f::ProductFun,ox::TensorSpace) = coefficients(f,ox[1],ox[2])

Expand Down Expand Up @@ -276,7 +279,6 @@ canonicalevaluate(f::ProductFun,xx::AbstractVector,yy::AbstractVector) =


evaluate(f::ProductFun,x,y) = canonicalevaluate(f,tocanonical(f,x,y)...)
evaluate(f::ProductFun,x,y,z) = canonicalevaluate(f,tocanonical(f,x,y,z)...)

# TensorSpace does not use map
evaluate(f::ProductFun{S,V,SS,T},x::Number,::Colon) where {S<:UnivariateSpace,V<:UnivariateSpace,SS<:TensorSpace,T} =
Expand All @@ -286,6 +288,7 @@ evaluate(f::ProductFun{S,V,SS,T},x::Number,y::Number) where {S<:UnivariateSpace,
evaluate(f,x,:)(y)



evaluate(f::ProductFun,x) = evaluate(f,x...)

*(c::Number,f::F) where {F<:ProductFun} = F(c*f.coefficients,f.space)
Expand Down
99 changes: 91 additions & 8 deletions src/Multivariate/TensorSpace.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,76 @@ struct Tensorizer{DMS<:Tuple}
blocks::DMS
end

const Tensorizer2D{AA, BB} = Tensorizer{Tuple{AA, BB}}
const TrivialTensorizer{d} = Tensorizer{NTuple{d,Ones{Int,1,Tuple{OneToInf{Int}}}}}

Base.eltype(a::Tensorizer) = NTuple{length(a.blocks),Int}
Base.eltype(::Tensorizer{<:NTuple{d}}) where {d} = NTuple{d,Int}
dimensions(a::Tensorizer) = map(sum,a.blocks)
Base.length(a::Tensorizer) = mapreduce(sum,*,a.blocks)


function start(a::TrivialTensorizer{d}) where {d}
if d==2
return invoke(start, Tuple{Tensorizer2D}, a)
else
# ((block_dim_1, block_dim_2,...), (itaration_number, iterator, iterator_state)), (itemssofar, length)
return (ones(Int, d),(0, nothing, nothing)), (0,length(a))
end
end

function next(a::TrivialTensorizer{d}, iterator_tuple) where {d}

if d==2
return invoke(next, Tuple{Tensorizer2D, Tuple}, a, iterator_tuple)
end

(block, (j, iterator, iter_state)), (i,tot) = iterator_tuple


@inline function check_block_finished()
if iterator === nothing
return true
end
# there are N-1 over d-1 combinations in a block
amount_combinations_block = binomial(sum(block)-1, d-1)
# check if all combinations have been iterated over
amount_combinations_block <= j
end

ret = reverse(block)

if check_block_finished() # end of new block

# set up iterator for new block
current_sum = sum(block)
iterator = multiexponents(d, current_sum+1-d)
iter_state = nothing
j = 0
end

# increase block, or initialize new block
res, iter_state = iterate(iterator, iter_state)
block .= res.+1
j = j+1

ret, ((block, (j, iterator, iter_state)), (i,tot))
end


function done(a::TrivialTensorizer{d}, iterator_tuple) where {d}
if d==2
return invoke(done, Tuple{Tensorizer2D, Tuple}, a, iterator_tuple)
end
(_, (i,tot)) = iterator_tuple
return i ≥ tot
end


# (blockrow,blockcol), (subrow,subcol), (rowshift,colshift), (numblockrows,numblockcols), (itemssofar, length)
start(a::Tensorizer{Tuple{AA,BB}}) where {AA,BB} = (1,1), (1,1), (0,0), (a.blocks[1][1],a.blocks[2][1]), (0,length(a))
start(a::Tensorizer2D{AA, BB}) where {AA,BB} = (1,1), (1,1), (0,0), (a.blocks[1][1],a.blocks[2][1]), (0,length(a))

function next(a::Tensorizer{Tuple{AA,BB}}, ((K,J), (k,j), (rsh,csh), (n,m), (i,tot))) where {AA,BB}
function next(a::Tensorizer2D{AA, BB}, ((K,J), (k,j), (rsh,csh), (n,m), (i,tot))) where {AA,BB}
ret = k+rsh,j+csh
if k==n && j==m # end of block
if J == 1 || K == length(a.blocks[1]) # end of new block
Expand All @@ -59,7 +118,7 @@ function next(a::Tensorizer{Tuple{AA,BB}}, ((K,J), (k,j), (rsh,csh), (n,m), (i,t
end


done(a::Tensorizer, ((K,J), (k,j), (rsh,csh), (n,m), (i,tot))) = i ≥ tot
done(a::Tensorizer2D, ((K,J), (k,j), (rsh,csh), (n,m), (i,tot))) = i ≥ tot

iterate(a::Tensorizer) = next(a, start(a))
function iterate(a::Tensorizer, st)
Expand Down Expand Up @@ -104,6 +163,14 @@ block(ci::CachedIterator{T,TrivialTensorizer{2}},k::Int) where {T} =
block(::TrivialTensorizer{2},n::Int) =
Block(floor(Integer,sqrt(2n) + 1/2))

function block(::TrivialTensorizer{d},n::Int) where {d}
order::Int = 0
while binomial(order+d, d) < n
order = order + 1
end
return Block(order+1)
end

block(sp::Tensorizer{<:Tuple{<:AbstractFill{S},<:AbstractFill{T}}},n::Int) where {S,T} =
Block(floor(Integer,sqrt(2floor(Integer,(n-1)/(getindex_value(sp.blocks[1])*getindex_value(sp.blocks[2])))+1) + 1/2))
_cumsum(x) = cumsum(x)
Expand Down Expand Up @@ -211,6 +278,10 @@ struct TensorSpace{SV,D,R} <:AbstractProductSpace{SV,D,R}
spaces::SV
end

# Tensorspace of 2 univariate spaces
const TensorSpace2D{AA, BB, D,R} = TensorSpace{<:Tuple{AA, BB}, D, R} where {AA<:UnivariateSpace, BB<:UnivariateSpace}
const TensorSpaceND{d, D, R} = TensorSpace{<:NTuple{d, <:UnivariateSpace}, D, R}

tensorizer(sp::TensorSpace) = Tensorizer(map(blocklengths,sp.spaces))
blocklengths(S::TensorSpace) = tensorblocklengths(map(blocklengths,S.spaces)...)

Expand Down Expand Up @@ -473,6 +544,8 @@ end

fromtensor(S::Space,M::AbstractMatrix) = fromtensor(tensorizer(S),M)
totensor(S::Space,M::AbstractVector) = totensor(tensorizer(S),M)
totensor(SS::TensorSpace{<:NTuple{d}},M::AbstractVector) where {d} =
if d>2; totensoriterator(tensorizer(SS),M) else totensor(tensorizer(SS),M) end

function fromtensor(it::Tensorizer,M::AbstractMatrix)
n,m=size(M)
Expand All @@ -496,19 +569,27 @@ function totensor(it::Tensorizer,M::AbstractVector)
B=block(it,n)
ds = dimensions(it)

#ret=zeros(eltype(M),[sum(it.blocks[i][1:min(B.n[1],length(it.blocks[i]))]) for i=1:length(it.blocks)]...)

ret=zeros(eltype(M),sum(it.blocks[1][1:min(B.n[1],length(it.blocks[1]))]),
sum(it.blocks[2][1:min(B.n[1],length(it.blocks[2]))]))

k=1
for (K,J) in it
for index in it
if k > n
break
end
ret[K,J] = M[k]
ret[index...] = M[k]
k += 1
end
ret
end

@inline function totensoriterator(it::TrivialTensorizer{d},M::AbstractVector) where {d}
B=block(it,length(M))
return it, M, B
end

for OP in (:block,:blockstart,:blockstop)
@eval begin
$OP(s::TensorSpace, ::PosInfinity) = ℵ₀
Expand Down Expand Up @@ -542,10 +623,12 @@ end

itransform(sp::TensorSpace,cfs::AbstractVector) = vec(itransform!(sp,coefficientmatrix(Fun(sp,cfs))))

evaluate(f::AbstractVector,S::AbstractProductSpace,x) = ProductFun(totensor(S,f),S)(x...)
evaluate(f::AbstractVector,S::AbstractProductSpace,x,y) = ProductFun(totensor(S,f),S)(x,y)

# 2D evaluation functions
evaluate(f::AbstractVector,S::TensorSpace2D,x) = ProductFun(totensor(S,f), S)(x...)
evaluate(f::AbstractVector,S::TensorSpace2D,x,y) = ProductFun(totensor(S,f),S)(x,y)

# ND evaluation functions of Trivial Spaces
evaluate(f::AbstractVector,S::TensorSpaceND,x) = TrivialTensorFun(totensor(S, f)..., S)(x...)

coefficientmatrix(f::Fun{<:AbstractProductSpace}) = totensor(space(f),f.coefficients)

Expand Down
45 changes: 45 additions & 0 deletions src/Multivariate/TrivialTensorFun.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@



struct TrivialTensorFun{d, SS<:TensorSpaceND{d}, T<:Number} <: MultivariateFun{T, d}
space::SS
coefficients::Vector{T}
iterator::TrivialTensorizer{d}
orders::Block{1, Int}
end


function TrivialTensorFun(iter::TrivialTensorizer{d},cfs::Vector{T},blk::Block, sp::TensorSpaceND{d}) where {T<:Number,d}
if any(map(dimension, sp.spaces).!=ℵ₀)
error("This Space is not a Trivial Tensor space!")
end
TrivialTensorFun(sp, cfs, iter, blk)
end

(f::TrivialTensorFun)(x...) = evaluate(f, x...)

# TensorSpace evaluation
function evaluate(f::TrivialTensorFun{d, SS, T},x...) where {d, SS, T}
highest_order = f.orders.n[1]
n = length(f.coefficients)

# this could be lazy evaluated for the sparse case
A = T[Fun(f.space.spaces[i], [zeros(T, k);1])(x[i]) for k=0:highest_order, i=1:d]
result::T = 0
coef_counter::Int = 1
for i in f.iterator
tmp = f.coefficients[coef_counter]
if tmp != 0
tmp_res = 1
for k=1:d
tmp_res *= A[i[k], k]
end
result += tmp * tmp_res
end
coef_counter += 1
if coef_counter > n
break
end
end
return result
end