DataInterpolations.jl - defining function without broadcasting syntax

I’m trying to fit a curve using DataInterpolations.jl and want to fit a curve with some fixed and variable parameters. The fixed number of terms can vary, which is why I’m starting with a sum of a generator (below, take c being [0.2,0.4,0.6] as the fixed parameters). I’m trying to figure out how to get this to work without needing to write out the full expression for different lengths of fixed c vectors.

m(x,params) = sum(params[i+1]*exp(-c*x) for (i,c) in enumerate([0.2,0.4,0.6])) + params[1]
rates =[0.01, 0.01, 0.03, 0.05, 0.07, 0.16, 0.35, 0.92, 1.40, 1.74, 2.31, 2.41] ./ 100
mats = [1/12, 2/12, 3/12, 6/12, 1, 2, 3, 5, 7, 10, 20, 30]

Results in an error:

julia> Curvefit(rates,mats,m,ones(4),LBFGS())
ERROR: MethodError: no method matching exp(::Vector{Float64})

If I write out the whole function explicitly with broadcasting syntax it works:

m(x, params) = @. params[1] + params[2]*exp(-0.2*x) + params[3] * exp(-0.4*x) + params[4] * exp(-0.8*x)
julia> A = Curvefit(rates,mats,m,ones(4),LBFGS())
24-element DataInterpolations.CurvefitCache{Vector{Float64}, Vector{Float64}, typeof(m), Vector{Float64}, Nothing, Nothing, LBFGS{Nothing, LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Optim.var"#19#21"}, Vector{Float64}, true, Float64}:
  0.0001
  0.0001
  0.0003
  0.0005
  0.0007000000000000001
  0.0016
  0.0034999999999999996
  ⋮
  2.0
  3.0
  5.0
  7.0
 10.0
 20.0
 30.0

I tried writing a function that would return an array like I think the broadcasting version would do, but got an error as well:

m(x,params) = [sum(params[i+1]*exp(-c*x) for (i,c) in enumerate([0.2,0.4,0.6])) + params[1] for xi in x]

And the assocated error:

julia> Curvefit(rates,mats,m,ones(4),LBFGS())
ERROR: MethodError: no method matching exp(::Vector{Float64})

Are there suggested ways to do this?

This worked:

m(x,params) = sum(params[i+1]*exp.(-c.*x) for (i,c) in enumerate([0.2,0.4,0.6])) .+ params[1]
1 Like