I have an Expr
:([4.01673077 7.62137432 8.74459436 10.14775067 12.57379884 14.39781963; 17.00925227 19.2273262])
and I wish to transfer it into a Vector{Float64}, but calling eval on this directly does not seem to work.
How can I do this?
You can either extract the data from Expr (faster and safe) or just eval it (slower, unsafe, easier code).
julia> a = :([12.57379884 14.39781963; 17.00925227 19.2273262])
:([12.57379884 14.39781963; 17.00925227 19.2273262])
julia> [Float64.(vals) for vals in getfield.(a.args, :args)]
2-element Vector{Vector{Float64}}:
[12.57379884, 14.39781963]
[17.00925227, 19.2273262]
julia> eval(a)
2×2 Matrix{Float64}:
12.5738 14.3978
17.0093 19.2273
Your matrix is wrongly formed and hence only the first solution will work with it.
Related
Newbie Julia question here. Given two arrays,
W = [randn(3,2), randn(3,2)]
b = [randn(3), randn(3)]
I would like to do a "nested broadcast" along the lines of,
W .+ b = [W[1].+b[1], W[2].+b[2]]
So far the best I've been able to come up with is,
[Wi.+bi (Wi,bi) for zip(W,b)]
Coming from a Python background this feels sacrilegious. Is there a better way to do this in Julia?
You could do something like the following:
julia> W = [randn(3,2), randn(3,2)]
2-element Array{Array{Float64,2},1}:
[0.39179718902868116 -0.5387622679356612; -0.594274465053327 0.018804631512093436; -2.273706742420988 -0.4638617400026042]
[0.3249960563405678 -0.4877554417492699; 0.5036437919340767 1.3172770503034696; 0.03501532820428975 -0.2675024677340758]
julia> b = [randn(3), randn(3)]
2-element Array{Array{Float64,1},1}:
[1.2571527266220441, 0.21599608118129476, 0.21498843153804936]
[-0.528960345932853, 0.5610435189953311, -0.8636370930615718]
# A helper function which broadcasts once
julia> s_(Wi, bi) = Wi .+ bi
s_ (generic function with 1 method)
# Broadcast the helper function
julia> s_.(W, b)
2-element Array{Array{Float64,2},1}:
[1.6489499156507252 0.718390458686383; -0.3782783838720323 0.2348007126933882; -2.0587183108829388 -0.24887330846455485]
[-0.20396428959228524 -1.016715787682123; 1.0646873109294077 1.8783205692988008; -0.828621764857282 -1.1311395607956476]
As mentioned in comments, you can use one of the available user-definable infix operators to name the helper function, which allows for a nicer syntax (the particular symbol used below can be obtained by typing \oplus then Tab):
julia> ⊕(x, y) = x .+ y
⊕ (generic function with 1 method)
julia> W .⊕ b
2-element Array{Array{Float64,2},1}:
[1.6489499156507252 0.718390458686383; -0.3782783838720323 0.2348007126933882; -2.0587183108829388 -0.24887330846455485]
[-0.20396428959228524 -1.016715787682123; 1.0646873109294077 1.8783205692988008; -0.828621764857282 -1.1311395607956476]
Or - again as mentioned in comments - if you don't feel like explicitly declaring a helper function:
julia> ((Wi, bi)->Wi.+bi).(W, b)
2-element Array{Array{Float64,2},1}:
[1.6489499156507252 0.718390458686383; -0.3782783838720323 0.2348007126933882; -2.0587183108829388 -0.24887330846455485]
[-0.20396428959228524 -1.016715787682123; 1.0646873109294077 1.8783205692988008; -0.828621764857282 -1.1311395607956476]
(I personally have more difficulty reading that last version, but YMMV)
When you want to broadcast broadcast, then broadcast broadcast:
julia> broadcast.(+, W, b)
2-element Array{Array{Float64,2},1}:
[-0.7364111670769904 0.010994354421031916; -0.9010128415786036 0.22868802910609998; 1.2030371118617933 0.21305414210853912]
[0.19183885867446926 0.5362077496502086; 1.5909421118115665 0.1235808501390212; 1.5190965380769597 0.1883638848487652]
julia> [W[1].+b[1], W[2].+b[2]]
2-element Array{Array{Float64,2},1}:
[-0.7364111670769904 0.010994354421031916; -0.9010128415786036 0.22868802910609998; 1.2030371118617933 0.21305414210853912]
[0.19183885867446926 0.5362077496502086; 1.5909421118115665 0.1235808501390212; 1.5190965380769597 0.1883638848487652]
I want to assign the result of an operation to a concatenation of variables in Julia. Something similar to this (although this doesn't work):
a = zeros(5)
b = zeros(5)
a, b .= rand(10)
Is it possible? Thank you.
You are looking for "vector view concatenation". The idea here is to use SubArrays to build an Array that is actually a view into two arrays. Julia does not support this out of the box. The Julia package ChainedVectors.jl was built for this, but it is heavily outdated and only works with Julia <= 0.4.
Not everything is lost. You have two alternatives:
Use CatViews.jl
As pointed out in the comments, CatViews.jl is like ChainedVectors.jl, but works with Julia 0.6 and 0.7:
Pkg.add("CatViews")
using CatViews
a = zeros(2)
b = zeros(2)
CatView(a, b) .= rand(4)
Build your own solution
With a little work, we can get as good as
a = zeros(2)
b = zeros(2)
MyView(a, b) .= rand(4)
Julia allows you to build your own view-concatenation type. The effort required to build it scales proportional to how general you want it to be. Here is a first attempt that works with vectors:
julia> # Create a type for a view into two vectors.
julia> type MyView{T} <: AbstractVector{T}
a::Vector{T}
b:: Vector{T}
end
julia> import Base: size, getindex, setindex!
julia> # Define methods to make MyView behave properly.
julia> size(c::MyView) = size(c.a) .+ size(c.b)
julia> getindex(c::MyView, i::Int) = i <= length(c.a) ? getindex(a, i) : getindex(b, i-length(a))
julia> setindex!(c::MyView, val, i::CartesianIndex) = i[1] <= length(c.a) ? setindex!(c.a, val, i[1]) : setindex!(c.b, val, i[1]-length(a))
julia> setindex!(c::MyView, val, i::Int) = i <= length(c.a) ? setindex!(c.a, val, i) : setindex!(c.b, val, i-length(a))
julia> # Test MyView. Define two arrays and put them
julia> # into a single view.
julia> a = rand(2)
2-element Array{Float64,1}:
0.701867
0.543514
julia> b = rand(2)
2-element Array{Float64,1}:
0.00355893
0.405809
julia> MyView(a, b) .= rand(4)
4-element MyView{Float64}:
0.922896
0.969057
0.586866
0.457117
julia> # Hooray, it worked! As we see below,
julia> # the individual arrays were updated.
julia> a
2-element Array{Float64,1}:
0.922896
0.969057
julia> b
2-element Array{Float64,1}:
0.586866
0.457117
This?
a .= x[1:5]
b .= x[6:end]
You must tell Julia somehow where to split the vector.
I am trying to port some code and now I've hit a sticky bit. The original code is in C++. I need to port a union that has two 32 bit ints (in an array) and a double.
So far I have:
I1 = UInt32(56) # arbitrary integer values for example
I2 = UInt32(1045195987)
# do transforms on I1 and I2 as per the code I'm porting
A = bits(I1)
B = bits(I2)
return parse(Float64, string(A,B))
Is this the way to do it? The string operation seems expensive. Any advice appreciated.
I also come from mostly C/C++ programming, and this is what I do to handle the problem:
First, create an immutable type with two UInt32 elements:
immutable MyType
a::UInt32
b::UInt32
end
Then you can convert a vector of Float64 to that type with reinterpret.
For example:
julia> x = [1.5, 2.3]
2-element Array{Float64,1}:
1.5
2.3
julia> immutable MyType ; a::UInt32 ; b::UInt32 ; end
julia> y = reinterpret(MyType, x)
2-element Array{MyType,1}:
MyType(0x00000000,0x3ff80000)
MyType(0x66666666,0x40026666)
julia> x[1]
1.5
julia> y[1]
MyType(0x00000000,0x3ff80000)
julia> y[1].a
0x00000000
julia> y[1].b
0x3ff80000
Note: the two vectors still point to the same memory, so you can even update elements, using either type.
julia> x[1] = 10e91
1.0e92
julia> y[1].a
0xbf284e24
julia> y[1].b
0x53088ba3
julia> y[1] = MyType(1,2)
MyType(0x00000001,0x00000002)
julia> x[1]
4.2439915824e-314
I followed the documentation of julia:
julia> :(a in (1,2,3))
:($(Expr(:in, :a, :((1,2,3)))))
Now that :(a in (1,2,3))==:($(Expr(:in, :a, :((1,2,3))))), why does julia express this expression in this way? And what does $ exactly means? It seems to me that $ just evaluates the next expression in a global scope. I found the documentation unclear about this.
The reason :(a in (1,2,3)) is displayed awkwardly as :($(Expr(...))) is because the show function for Expr typed objects (show_unquoted in show.jl) does not understand the in infix operator and fallbacks into a generic printing format.
Essentially it is the same as :(1 + 1) except that show_unquoted recognizes + as an infix operator and formats it nicely.
In any case, :(...) and $(...) are inverse operators in some sense, so :($(..thing..)) is exactly like ..thing.., which in this case is Expr(:in,:a,:((1,2,3))).
One can see this weirdness in :(1+1) for example. The output is of Expr type, as typeof(:(1+1))==Expr confirms. It is actually Expr(:+,1,1), but typing Expr(:+,1,1) on the REPL will show :($(Expr(:+,1,1))) - the generic formatting style of Expr typed objects.
Fixing show.jl to handle in could be a nice change. But the issue is harmless and concerns display formatting.
$ is the interpolation command, Julia use this notation to interpolate Strings as well as Expression:
julia> a=1;
julia> "test $a" # => "test 1"
julia> :(b+$a) # => :(b + 1)
When you type a command in Julia REPL, it tries to evaluates the command and if the code do not have ; char at the end it prints the result, so it's more related to printing functions, that what will be seen on REPL, when a command executes.
so if you want to see the real contents of a variable one possibility is to use dump function:
julia> dump(:(a+b))
Expr
head: Symbol call
args: Array(Any,(3,))
1: Symbol +
2: Symbol a
3: Symbol b
typ: Any
julia> dump(:(a in b))
Expr
head: Symbol in
args: Array(Any,(2,))
1: Symbol a
2: Symbol b
typ: Any
It's clear from above tests, that both expressions use a common data structure of Expr with head, args and typ without any $ inside.
Now try to evaluate and print result:
julia> :(a in b)
:($(Expr(:in, :a, :b)))
julia> :(a+b)
:(a + b)
We already know that both command create a same structure but REPL can't show the result of :(a in b) better that an Expr of result of another Expr and it's why there in a $ inside. But when dealing with :(a+b), REPL do more intelligently and understands that this:
Expr
head: Symbol call
args: Array(Any,(3,))
1: Symbol +
2: Symbol a
3: Symbol b
typ: Any
is equal to :(a+b).
Accordingly to the standard function names, Expr type is said to follow this simple structure:
julia> names(Expr)
3-element Array{Symbol,1}:
:head
:args
:typ
Therefore, I expect to be able to build an Expr from a direct call of the Expr constructor with this following trivial method, from another Expr:
julia> exp1 = :(x+y);
julia> exp2 = Expr(exp1.head,exp1.args,exp1.typ)
:(({:+,:x,:y})(Any))
But the resulting exp2 does not contain the same args as exp1; Expr build the new args from exp1.args and exp1.typ :
julia> exp2.args
2-element Array{Any,1}:
{:+,:x,:y}
Any
vs
julia> exp1.args
3-element Array{Any,1}:
:+
:x
:y
What did I do wrong?
Edit:
Following the Varargs section of the documentation, it is also possible to splice an iterable object into a function call. So in my case, it simply goes:
julia> Expr(:call,exp1.args...)
:(x+y)
The Expr() constructor doesn't map the inputs directly to the fields of the Expr type. Rather the first input becomes the head and the rest of the inputs become the args. So to construct the expression x + y using the Expr constructor you would do:
Expr(:call, :(+), :x, :y)