Problem when adding up Function expressions

I am trying to have a function that returns Function type in a vector, now I want to add all the elements of the vector to return again a Function type and then I want plot this Function. Here is my code snippet.

function proj(N::Int,n::Int,l::Int,k::Int,analy_func::Function)
    ci=nodeCoeffs(N,n,l,k,fun)
    phi=nodeScalingFunctions(N,n,l,k,fun)
    f(x) = sum(ci[i]*phi[i](x) for i in 1:k) 
    return f
end

And nodeCoeffs() is a function that returns a Vector{Float64} and nodeScalingFunction() is a function which returns a Vector{Function}. I also attach the two functions below for reference.

function nodeCoeffs(N::Int,n::Int,l::Int,k::Int,analy_func::Function)
    Snode=[computeScalingCoeff(N,n,l,i,analy_func) for i in 0:k-1]
    return Snode
end

and

function nodeScalingFunctions(N::Int,n::Int,l::Int,k::Int,analy_func::Function)
    phiarray=Array{Function, 1}(undef, k)
    for i=1:k 
        phitmp(x) = getMotherScalingFunction(n,l,i,x)
        phiarray[i]=phitmp
    end
    return phiarray
end

Everytime I am running the proj() function I am getting “no method matching” error or something else like “x is not defined” or “f is not defined”. Please help me in this regard and if anyone knows an elegant way to solve this issue.

The obvious issue is that fun is not defined in proj. I suspect that the last arg should be fun?

More generally, you should aim to post a Minimal Working Example that is self-contained (and minimal) and a specific error message to be resolved.

Finally, your approach seems a bit roundabout. Instead of storing a bunch of functions in phi and then adding them up, why not let f(x) directly evaluate the functions?

1 Like

Okay I made corrections, I now try to put a simple example of what I wish to achieve so that it is clearer to the people.

Math
I want a linear combination of some functions and then I wish to plot them and use them in further cases. We have coefficient vector c and functions of x as phi and the formula follows:

$$ f(x) = \sum_i c_i * phi[i] $$

function makefunc(n::Int, x)
    if(n==0)
        return 1.0
    elseif(n==1)
        return x
    elseif(n==2)
        return x^2
    end
end

function makefuncproj(n::Int,x)
    c=[2.0^i for i in 1:n]
    f(x)=0.0*x
    for i in 1:n
        f +=c[i]*makefunc(i,x)
    end
    return f
end

fnew(x) = makefuncproj(2,x)
plot(fnew, xlimits=(0,1))

And this is giving me this output

	"name": "MethodError",
	"message": "MethodError: no method matching +(::var\"#f#35\", ::Float64)

Closest candidates are:
  +(::Any, ::Any, !Matched::Any, !Matched::Any...)
   @ Base operators.jl:578
  +(!Matched::T, ::T) where T<:Union{Float16, Float32, Float64}
   @ Base float.jl:408
  +(!Matched::UniformScaling, ::Number)
   @ LinearAlgebra ~/.julia/juliaup/julia-1.9.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.9/LinearAlgebra/src/uniformscaling.jl:144
  ...
",
	"stack": "MethodError: no method matching +(::var\"#f#35\", ::Float64)

Closest candidates are:
  +(::Any, ::Any, !Matched::Any, !Matched::Any...)
   @ Base operators.jl:578
  +(!Matched::T, ::T) where T<:Union{Float16, Float32, Float64}
   @ Base float.jl:408
  +(!Matched::UniformScaling, ::Number)
   @ LinearAlgebra ~/.julia/juliaup/julia-1.9.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.9/LinearAlgebra/src/uniformscaling.jl:144
  ...


Stacktrace:
  [1] makefuncproj(n::Int64, x::Float64)
    @ Main ~/Documents/Presentations/hu0.1/src/polynomials.ipynb:15
  [2] fnew(x::Float64)
    @ Main ~/Documents/Presentations/hu0.1/src/polynomials.ipynb:20
  [3] call_composed (repeats 2 times)
    @ ./operators.jl:1034 [inlined]
  [4] (::ComposedFunction{ComposedFunction{RecipesPipeline.var\"#1#2\"{Symbol}, typeof(fnew)}, RecipesPipeline.var\"#3#4\"{Symbol}})(x::Float64; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./operators.jl:1031
  [5] (::ComposedFunction{ComposedFunction{RecipesPipeline.var\"#1#2\"{Symbol}, typeof(fnew)}, RecipesPipeline.var\"#3#4\"{Symbol}})(x::Float64)
    @ Base ./operators.jl:1031
  [6] (::PlotUtils.var\"#21#23\"{ComposedFunction{ComposedFunction{RecipesPipeline.var\"#1#2\"{Symbol}, typeof(fnew)}, RecipesPipeline.var\"#3#4\"{Symbol}}})(x::Float64)
    @ PlotUtils ~/.julia/packages/PlotUtils/mHQ0Q/src/adapted_grid.jl:49
  [7] _broadcast_getindex_evalf
    @ ./broadcast.jl:683 [inlined]
  [8] _broadcast_getindex
    @ ./broadcast.jl:656 [inlined]
  [9] getindex
    @ ./broadcast.jl:610 [inlined]
 [10] macro expansion
    @ ./broadcast.jl:974 [inlined]
 [11] macro expansion
    @ ./simdloop.jl:77 [inlined]
 [12] copyto!
    @ ./broadcast.jl:973 [inlined]
 [13] copyto!
    @ ./broadcast.jl:926 [inlined]
 [14] copy
    @ ./broadcast.jl:898 [inlined]
 [15] materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, PlotUtils.var\"#21#23\"{ComposedFunction{ComposedFunction{RecipesPipeline.var\"#1#2\"{Symbol}, typeof(fnew)}, RecipesPipeline.var\"#3#4\"{Symbol}}}, Tuple{Vector{Float64}}})
    @ Base.Broadcast ./broadcast.jl:873
 [16] adapted_grid(f::Any, minmax::Tuple{Float64, Float64}; max_recursions::Int64, max_curvature::Float64, n_points::Int64)
    @ PlotUtils ~/.julia/packages/PlotUtils/mHQ0Q/src/adapted_grid.jl:60
 [17] adapted_grid(f::Any, minmax::Tuple{Float64, Float64})
    @ PlotUtils ~/.julia/packages/PlotUtils/mHQ0Q/src/adapted_grid.jl:14
 [18] _scaled_adapted_grid(f::Function, xscale::Symbol, yscale::Symbol, xmin::Int64, xmax::Int64)
    @ RecipesPipeline ~/.julia/packages/RecipesPipeline/BGM3l/src/user_recipe.jl:322
 [19] macro expansion
    @ ~/.julia/packages/RecipesPipeline/BGM3l/src/user_recipe.jl:265 [inlined]
 [20] apply_recipe(plotattributes::AbstractDict{Symbol, Any}, f::Function, xmin::Number, xmax::Number)
    @ RecipesPipeline ~/.julia/packages/RecipesBase/BRe07/src/RecipesBase.jl:300
 [21] _process_userrecipes!(plt::Any, plotattributes::Any, args::Any)
    @ RecipesPipeline ~/.julia/packages/RecipesPipeline/BGM3l/src/user_recipe.jl:38
 [22] recipe_pipeline!(plt::Any, plotattributes::Any, args::Any)
    @ RecipesPipeline ~/.julia/packages/RecipesPipeline/BGM3l/src/RecipesPipeline.jl:72
 [23] _plot!(plt::Plots.Plot, plotattributes::Any, args::Any)
    @ Plots ~/.julia/packages/Plots/sxUvK/src/plot.jl:223
 [24] plot(args::Any; kw::Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}})
    @ Plots ~/.julia/packages/Plots/sxUvK/src/plot.jl:102
 [25] top-level scope
    @ ~/Documents/Presentations/hu0.1/src/polynomials.ipynb:21"
}

It’s possible I’m missing something, but this looks weird to me. You construct a vector c that will be [2.0, 4.0] when n=2. Then you create a Function called f that maps x to 0.0x, i.e. a function f(x) = 0.0. Then you’re trying to add Float64 values to a Function. It seems like maybe you’re intending f(x) to actually represent some concrete value, e.g. y = 0.0x.

Edit:
I just re-read your earlier post. It looks like what you’re trying to achieve is a new function whose value is the prior function’s value plus some new components. In that case, the error is that adding to a Function isn’t defined. Instead, you could try something like the following (totally made up values, just trying to demonstrate the structure).

f(c,x) = 2x + c

c = [2.0, 4.0]
g(x) = 1.0 + sum(c .* f.(c,x))

return g
1 Like

If I understand your notation correctly, it seems like you just want something like

makefunc(c, ϕ) = x -> sum((cᵢ,ϕᵢ) -> cᵢ * ϕᵢ(x), zip(c, ϕ)).

You can’t add functions per se, e.g. sin + cos in Julia is not allowed, but you can construct and compose new functions like x -> sin(x) + cos(x) as needed.