In the performance tip, it says f(x::Int...) = tuple(x...) will not specialize. It also suggests to use (#which f(...)).specializations to check the specializations.
f(x::Int...) = tuple(x...)
f(1)
f(1, 2)
f(1, 2, 3)
f(1, 2, 3, 4)
a = first(methods(f)).specializations
Core.TypeMapEntry(Core.TypeMapEntry(nothing, Tuple{typeof(f),Int64}, nothing, svec(), 0x0000000000000001, 0xffffffffffffffff, MethodInstance for f(::Int64), true, true, false), Tuple{typeof(f),Int64,Vararg{Int64,N} where N}, nothing, svec(), 0x0000000000000001, 0xffffffffffffffff, MethodInstance for f(::Int64, ::Vararg{Int64,N} where N), false, true, true)
How do I interpret the TypeMapEntry? How can I access it programatically (I find it hard to read from the output)? How many specializations has it made?
The MethodAnalysis package, registered just this morning, should give you everything you need. (Your timing in asking this question was excellent!)
Related
so I wrote a minimum example to show what I'm trying to do. Basically I want to solve a optimization problem with multiple variables. When I try to do this in JuMP I was having issues with my function obj not being able to take a forwardDiff object.
I looked here: and it seemed to do with the function signature :Restricting function signatures while using ForwardDiff in Julia . I did this in my obj function, and for insurance did it in my sub-function as well, but I still get the error
LoadError: MethodError: no method matching Float64(::ForwardDiff.Dual{ForwardDiff.Tag{JuMP.var"#110#112"{typeof(my_fun)},Float64},Float64,2})
Closest candidates are:
Float64(::Real, ::RoundingMode) where T<:AbstractFloat at rounding.jl:200
Float64(::T) where T<:Number at boot.jl:715
Float64(::Int8) at float.jl:60
This still does not work. I feel like I have the bulk of the code correct, just some weird of type thing going on that I have to clear up so autodifferentiate works...
Any suggestions?
using JuMP
using Ipopt
using LinearAlgebra
function obj(x::Array{<:Real,1})
println(x)
x1 = x[1]
x2 = x[2]
eye= Matrix{Float64}(I, 4, 4)
obj_val = tr(eye-kron(mat_fun(x1),mat_fun(x2)))
println(obj_val)
return obj_val
end
function mat_fun(var::T) where {T<:Real}
eye= Matrix{Float64}(I, 2, 2)
eye[2,2]=var
return eye
end
m = Model(Ipopt.Optimizer)
my_fun(x...) = obj(collect(x))
#variable(m, 0<=x[1:2]<=2.0*pi)
register(m, :my_fun, 2, my_fun; autodiff = true)
#NLobjective(m, Min, my_fun(x...))
optimize!(m)
# retrieve the objective value, corresponding x values and the status
println(JuMP.value.(x))
println(JuMP.objective_value(m))
println(JuMP.termination_status(m))
Use instead
function obj(x::Vector{T}) where {T}
println(x)
x1 = x[1]
x2 = x[2]
eye= Matrix{T}(I, 4, 4)
obj_val = tr(eye-kron(mat_fun(x1),mat_fun(x2)))
println(obj_val)
return obj_val
end
function mat_fun(var::T) where {T}
eye= Matrix{T}(I, 2, 2)
eye[2,2]=var
return eye
end
Essentially, anywhere you see Float64, replace it by the type in the incoming argument.
I found the problem:
in my mat_fun the type of the return had to be "Real" in order for it to propgate through. Before it was Float64, which was not consistent with the fact I guess all types have to be Real with the autodifferentiate. Even though a Float64 is clearly Real, it looks like the inheritence isn't perserved i.e you have to make sure everything that is returned and inputed are type Real.
using JuMP
using Ipopt
using LinearAlgebra
function obj(x::AbstractVector{T}) where {T<:Real}
println(x)
x1 = x[1]
x2 = x[2]
eye= Matrix{Float64}(I, 4, 4)
obj_val = tr(eye-kron(mat_fun(x1),mat_fun(x2)))
#println(obj_val)
return obj_val
end
function mat_fun(var::T) where {T<:Real}
eye= zeros(Real,(2,2))
eye[2,2]=var
return eye
end
m = Model(Ipopt.Optimizer)
my_fun(x...) = obj(collect(x))
#variable(m, 0<=x[1:2]<=2.0*pi)
register(m, :my_fun, 2, my_fun; autodiff = true)
#NLobjective(m, Min, my_fun(x...))
optimize!(m)
# retrieve the objective value, corresponding x values and the status
println(JuMP.value.(x))
println(JuMP.objective_value(m))
println(JuMP.termination_status(m))
I have some problems with JuMP. When I run it, it says:
MethodError: no method matching (::Interpolations.Extrapolation{Float64, 1, ScaledInterpolation{Float64, 1, Interpolations.BSplineInterpolation{Float64, 1, Vector{Float64}, BSpline{Linear{Throw{OnGrid}}}, Tuple{Base.OneTo{Int64}}}, BSpline{Linear{Throw{OnGrid}}}, Tuple{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}}, BSpline{Linear{Throw{OnGrid}}}, Throw{Nothing}})(::AffExpr)
Use square brackets [] for indexing an Array.
thanks!
using JuMP
import Ipopt
β = 0.88
Nb = 1000
δ = 1.5
wage = 1
rate = 1
grid_b = range(0, 5, length = 1000)
w = 5 * (grid_b).^2
w_func = LinearInterpolation(grid_b, w)
choice1 = Model(Ipopt.Optimizer)
#variable(choice1, x >= 0)
#NLobjective(choice1, Max, x^δ/(1-δ) + β * (w_func.((grid_b[3]*(1+rate)+wage-x) * 3)))
optimize!(choice1)
If I try to run your code, I get
ERROR: UndefVarError: LinearInterpolation not defined
which package is that from? Also, what version of JuMP are you using?
You can’t use arbitrary functions in JuMP. You need to use a user-defined function:
https://jump.dev/JuMP.jl/stable/manual/nlp/#User-defined-Functions
But this will only work if it’s possible to automatically differentiate the function. I don’t know if that works with Interpolations.jl.
p.s. Please provide a link when posting the same question in multiple places: https://discourse.julialang.org/t/methoderror-no-method-matching-in-jump/66543/2
I'm trying to convert the following to pointfree style: a function that partially applies a value to the transformer function add before passing in the collection to be iterated over. (Using Ramda.js)
R.compose(
R.map,
R.add
)(1, [1,2,3])
The problem is that R.add is arity 2, as is R.map. I want the application order to be as follows:
add(1)
map(add(1))
map(add(1), [1,2,3])
[add(1,1), add(1,2), add(1,3)]
But what happens instead is this:
add(1, [1,2,3])
map(add(1, [1,2,3]))
<partially applied map, waiting for collection>
Anyone know of a way to specify this behavior?
A plain compose or pipe won't do this because either will absorb all the arguments supplied into the first function. Ramda includes two additional functions that help with this, converge and useWith. In this case useWith is the one that will help:
useWith(map, [add, identity])(1, [1, 2, 3]); //=> [2, 3, 4]
While identity is not absolutely required here, it gives the generated function the correct arity.
Figured it out. If anyone's curious, here's the gist. (You can try it in the console on RamdaJS.com.)
0) For a baseline, here's the pointed version.
func0 = x => R.map(R.add(x))
addOne = func0(1)
addOne([1,2,3]) // [2,3,4]
1) Here's the pointfree core, but it has the ordering problem from the question above.
func1 = R.compose(R.map, R.add)
addOne = func1(1)
addOne([1,2,3]) // [2,3,4])
func1(1, [1,2,3]) // function
2) If the composition is unary (arity 1) 2 invocations are needed apply all params.
func2 = R.unary(R.compose(R.map, R.add))
addOne = func2(1)
addOne([1,2,3]) // [2,3,4])
3) We want one invocation to apply both params, so we uncurry 2.
func3 = R.uncurryN(2, func2)
func3(1, [1,2,3]) // [2,3,4])
4) To prove func2 is composable, let's double the results.
func4 = R.compose(
R.map(R.multiply(2)),
R.uncurryN(2, func2)
)
func4(1, [1,2,3]) // [4,6,8])
5) Substitution gives us a completely pointfree function.
func5 = R.compose(
R.map(R.multiply(2)),
R.uncurryN(2, R.unary(R.compose(
R.map,
R.add
)))
)
func5(1, [1,2,3]) // [4,6,8])
Simple function in Elixir, returning a list of numbers from to:
defmodule MyList do
def span(_), do: raise "Should be 2 args"
def span(from, to) when from > to, do: [ to | span(to + 1, from) ]
def span(from, to) when from < to, do: [ from | span(from + 1, to) ]
def span(from, to) when from == to, do: [ from ]
end
I have no slightest clue, why this works and return a list of numbers.
MyList.span(1,5)
#=> [1,2,3,4,5]
I just can't get my head around this:
[ from | span(from + 1, to) ]
Ok, first loop, I assume, would return the following:
[ 1 | span(2, 5) ]
What is next? [ 1, 2 | span(3, 5) ] ? Why?
How does it know, when to stop? Why is it even working?
Please, do not chase the points - don't bother answering, if you are not going to make an effort to make things clear(er) for functional programmer noob (OO programmer).
As a bonus to the answer you could provide me with a tips on how to start think recursively? Is there any panacea?
How does it keep track of the head? How does the function creates new list on each iteration keeping the values produced in the previous?
Thanks!
Ok, let's give this a shot.
Erlang evaluates function calls with a call-by-value strategy. From the linked wikipedia:
[call-by-value is a] family of evaluation strategies in which a function's argument is evaluated before being passed to the function.
What this means is that when Elixir (or rather Erlang) sees a function call with some arguments, it evaluates the arguments (which can obviously be expressions as well) before calling the function.
For example, let's take this function:
def add(a, b), do: a + b
If I call it with two expressions as arguments, those expressions will be evaluated before the the results are added up:
add(10 * 2, 5 - 3)
# becomes:
add(20, 2)
# kind of becomes:
20 + 2
# which results in:
22
Now that we get call-by-value, let's think of the | construct in list as a function for a moment. Think of it like if it would be used like this:
|(1, []) #=> [1]
|(29, [1, 2, 3]) #=> [29, 1, 2, 3]
As all functions, | evaluates its arguments before doing its work (which is creating a new list with the first argument as the first element and the second argument as the rest of the list).
When you call span(1, 5), it kind of expands (let's say it expands) to:
|(1, span(2, 5))
Now, since all arguments to | have to be evaluated before being able to actually prepend 1 to span(2, 5), we have to evaluate span(2, 5).
This goes on for a while:
|(1, |(2, span(3, 5)))
|(1, |(2, |(3, span(4, 5))))
|(1, |(2, |(3, |(4, span(5, 5)))))
|(1, |(2, |(3, |(4, [5]))))))
# now, it starts to "unwind" back:
|(1, |(2, |(3, [4, 5])))
|(1, |(2, [3, 4, 5]))
|(1, [2, 3, 4, 5])
[1, 2, 3, 4, 5]
(sorry if I'm using this |() syntax, remember I'm just using | as a function instead of an operator).
Nothing keeps track of the head and no function "keeps the values produced in the previous [iteration]". The first call (span(1, 5)) just expands to [1|span(2, 5)]. Now, in order for the span(1, 5) call to return, it needs to evaluate [1|span(2, 5)]: there you have it, recursion! It will need to evaluate span(2, 5) first and so on.
Technically, the values are kept somewhere, and it's on the stack: each function call is placed on the stack and popped off only when it's able to return. So the stack will look something like the series of calls I showed above:
# First call is pushed on the stack
span(1, 5)
# Second call is pushed on top of that
span(1, 5), span(2, 5)
# ...
span(1, 5), span(2, 5), ..., span(5, 5)
# hey! span(5, 5) is not recursive, we can return [5]. Let's pop span(5, 5) from the stack then
span(1, 5), ..., span(4, 5)
# Now span(4, 5) can return because we know the value of span(5, 5) (remember, span(4, 5) is expanded to [4|span(5, 5)]
This goes on until it goes back to span(1, 5) (which is now span(1, [2, 3, 4, 5])) and finally to [1, 2, 3, 4, 5].
Ok I wrote a lot and I'm not sure I made anything clearer to you :). Please, ask anything that's not clear. There are surely a lot of resources to learn recursion out there; just to name the first bunch I found:
The "Recursion" chapter of Learn You Some Erlang for Great Good, a great book on Erlang
Obligatory Wikipedia page on recursion
A nice page I just found about recursion on the khan academy website
Why not, a couple of Elixir-specific resources: the "Getting started" guide on Elixir's website, this blog post, this other blog post
Suppose we have a Vector of tuples (Int64, Int64) in julia:
In [1] xx = [(1, 2), (3, 4), (5, 6)]
typeof(xx) == Vector{(Int64, Int64)}
Out[1] true
Now I want to construct a new vector of the first indices of the tuples.
In [2] indices = [x[1] for x in xx]
typeof(indices)
Out[2] Array{Any, 1}
I expect it to be an Array{Int64, 1} type. How can I fix this?
edit: I am using 0.3.9.
function f()
xx = [(1, 2), (3, 4), (5, 6)]
inds = [ x[1] for x in xx ]
return(inds)
end
y = f()
typeof(y)
The last line of code returns Array{Int64, 1}.
The problem here is that you are working in global scope. For Julia's type inference to be able to do its magic, you need to work in a local scope. In other words, wrap all your code in functions. This rule is very, very, important, but, having come from a MatLab background myself, I can see why people forget it. Just remember, 90% of questions saying "Why is my Julia code slow?" occur because the user was working in global scope, not local scope.
ps, even in local scope, type inference of loop comprehensions can stumble in particularly complex cases. This is a known issue and is being worked on. If you want to provide the compiler with some "help" you can do something like:
inds = Int[ x[1] for x in xx ]
You can also use map and preserve the type:
#passing a lambda that takes the 1st element, and the iterable
inds = map( (x)-> x[1], xx)