What is the best way to get a number out of an inner product operation, rather than a 1x1 array. Is there a better way than this:
([1 2 3]*[4 5 6]')[1]
If possible, I wouldn't do the inner product manually, I'd use dot, i.e.
dot([1, 2, 3], [4, 5, 6])
I've noticed that you don't actually have vectors there though, instead you have 1x3 matrices (rows), so if thats really what you have you'd have to vec them first, which is a bit unpleasant:
dot(vec([1 2 3]), vec([4 5 6]))
Alternatively, one could do
sum([1 2 3].*[4 5 6])
which doesn't care about the dimensions.
Related
In Julia, you can permanently append elements to an existing vector using append! or push!. For example:
julia> vec = [1,2,3]
3-element Vector{Int64}:
1
2
3
julia> push!(vec, 4,5)
5-element Vector{Int64}:
1
2
3
4
5
# or
julia> append!(vec, 4,5)
7-element Vector{Int64}:
1
2
3
4
5
But, what is the difference between append! and push!? According to the official doc it's recommended to:
"Use push! to add individual items to a collection which are not already themselves in another collection. The result
of the preceding example is equivalent to push!([1, 2, 3], 4, 5, 6)."
So this is the main difference between these two functions! But, in the example above, I appended individual elements to an existing vector using append!. So why do they recommend using push! in these cases?
append!(v, x) will iterate x, and essentially push! the elements of x to v. push!(v, x) will take x as a whole and add it at the end of v. In your example there is no difference, since in Julia you can iterate a number (it behaves like an iterator with length 1). Here is a better example illustrating the difference:
julia> v = Any[]; # Intentionally using Any just to show the difference
julia> x = [1, 2, 3]; y = [4, 5, 6];
julia> push!(v, x, y);
julia> append!(v, x, y);
julia> v
8-element Vector{Any}:
[1, 2, 3]
[4, 5, 6]
1
2
3
4
5
6
In this example, when using push!, x and y becomes elements of v, but when using append! the elements of x and y become elements of v.
Since Julia is still in its early phase it'd be best if you follow the community standards, and one of the community standards, is your code making "sense" to other developers at first sight - I should know what your "intents" are immediately I read your code.
About append!, the doc says:
"For an ordered container collection, add the elements of each
collections to the end of it. !!! compat "Julia 1.6" Specifying
multiple collections to be appended requires at least Julia 1.6."
The append! method was added and requires Julia 1.6 to use for multiple collections; so in a sense it is the method that's going to be used in the future as Julia gets adopted a lot, Python uses it too, so adopters from there would likely use it too.
About push!, the doc says:
"Insert one or more items in collection. If collection is an ordered
container, the items are inserted at the end (in the given order). If
collection is ordered, use append! to add all the elements of another
collection to it."
The doc advises you use "append!" over "push!" when your collection is ordered. So as a Julia user, if I see append! on your code, I should know the collections its making changes on is in some way "ordered". That's just it. Otherwise, push! and append! does same things(something that might change in the future), but please follow community standards, it will help.
So use append! when you care about order and use push! when order doesn't matter in your collections. This way, any Julia user reading your code, will know your intents right away; but please don't mix them up
Let's say I have a vector V, and I want to either turn this vector into multiple m x n matrices, or get multiple m x n matrices from this Vector V.
For the most basic example: Turn V = collect(1:75) into 3 5x5 matrices.
As far as I am aware this can be done by first using reshape reshape(V, 5, :) and then looping through it. Is there a better way in Julia without using a loop?
If possible, a solution that can easily change between row-major and column-major results is preferrable.
TL:DR
m, n, n_matrices = 4, 2, 5
V = collect(1:m*n*n_matrices)
V = reshape(V, m, n, :)
V = permutedims(V, [2,1,3])
display(V)
From my limited knowledge about Julia:
When doing V = collect(1:m*n), you initialize a contiguous array in memory. From V you wish to create a container of m by n matrices. You can achieve this by doing reshape(V, m, n, :), then you can access the first matrix with V[:,:,1]. The "container" in this case is just another array (thus you have a three dimensional array), which in this case we interpret as "an array of matrices" (but you could also interpret it as a box). You can then transpose every matrix in your array by swapping the first two dimensions like this: permutedims(V, [2,1,3]).
How this works
From what I understand; n-dimensional arrays in Julia are contiguous arrays in memory when you don't do any "skipping" (e.g. V[1:2:end]). For example the 2 x 4 matrix A:
1 3 5 7
2 4 6 8
is in memory just 1 2 3 4 5 6 7 8. You simply interpret the data in a specific way, where the first two numbers makes up the first column, then the second two numbers makes the next column so on so forth. The reshape function simply specifies how you want to interpret the data in memory. So if we did reshape(A, 4, 2) we basically interpret the numbers in memory as "the first four values makes the first column, the second four values makes the second column", and we would get:
1 5
2 6
3 7
4 8
We are basically doing the same thing here, but with an extra dimension.
From my observations it also seems to be that permutedims in this case reallocates memory. Also, feel free to correct me if I am wrong.
Old answer:
I don't know much about Julia, but in Python using NumPy I would have done something like this:
reshape(V, :, m, n)
EDIT: As #BatWannaBe states, the result is technically one array (but three dimensional). You can always interpret a three dimensional array as a container of 2D arrays, which from my understanding is what you ask for.
For the sake of simplicity, I will refer to column as col.
Why are matrices defined as [rows, columns] and not [columns, rows]?
It has just caused me a ton of headaches and confusions.
My thinking goes this way:
A regular array:
[1, 3, 5, 2, 4]
is like a matrix with one row and multiple cols. And it is notated like that: arr[n].
And so if we had another dimension:
[1, 3, 5, 2, 4]
[1, 3, 6, 3, 6]
there are now rows. So let us notate the rows after the 'n', arr[n, rows], but the reality shows us otherwise.
In addition, a matrix of 2 dimensions can be looked at as a cartesian coordinate system (where the direction of the y axis is flipped, the origin is element [0,0]). in the plane, we notate points like that: (X,Y).
It looks like the cols are sitting on the x axis and the rows are on the y axis, so why not notate the elements of matrices like that: [Cols, Rows]?
Sorry if I've confused you, and sorry for my ignorance.
IMO, this is bound to latin typographical conventions.
Latin writes from left to right, then top to bottom.
Following these conventions, a Matrix is decomposed into nRow rows.
Each row is then decomposed into nColum elements, much like you would decompose a text in sentences, and sentences in words.
Information is thus organized with a most significant arrangement (rows) and least significant (column).
Following same convention as latin (err arabic) number notation, we have most significant nRow on the left (first if you are latin), and least significant nColumn on the right, thus (nRow,nColumn) for describing the layout.
Naturally, accessing a single element at row iRow and column jCol follows same convention (iRow,jCol).
Note that information can be arranged completely differently in underlying software. For example, for multi-dimensional arrays in FORTRAN and Matlab, first indice vary first, and the sequence in memory is x(1,1) x(2,1) x(3,1) ... x(1,2) x(2,2) x(3,2) ... sort of column-wise order if we consider that left (first) is row index, right (last) is column index. Or maybe some optimized library will have arranged a block layout for the matrix.
I picked up Julia to do some numerical analysis stuff and was trying to implement a full pivot LU decomposition (as in, trying to get an LU decomposition that is as stable as possible). I thought that the best way of doing so was finding the maximum value for each column and then resorting the columns in descending order of their maximum values.
Is there a way of avoiding swapping every element of two columns and instead doing something like changing two references/pointers?
Following up on #longemen3000's answer, you can use views to swap columns. For example:
julia> A = reshape(1:12, 3, 4)
3×4 reshape(::UnitRange{Int64}, 3, 4) with eltype Int64:
1 4 7 10
2 5 8 11
3 6 9 12
julia> V = view(A, :, [3,2,4,1])
3×4 view(reshape(::UnitRange{Int64}, 3, 4), :, [3, 2, 4, 1]) with eltype Int64:
7 4 10 1
8 5 11 2
9 6 12 3
That said, whether this is a good strategy depends on access patterns. If you'll use elements of V once or a few times, this view strategy is a good one. In contrast, if you access elements of V many times, you may be better off making a copy or moving values in-place, since that's a price you pay once whereas here you pay an indirection cost every time you access a value.
Just for "completeness", in case you actually want to swap columns in-place,
function swapcols!(X::AbstractMatrix, i::Integer, j::Integer)
#inbounds for k = 1:size(X,1)
X[k,i], X[k,j] = X[k,j], X[k,i]
end
end
is simple and fast.
In fact, in an individual benchmark for small matrices this is even faster than the view approach mentioned in the other answers (views aren't always free):
julia> A = rand(1:10,4,4);
julia> #btime view($A, :, $([3,2,1,4]));
31.919 ns (3 allocations: 112 bytes)
julia> #btime swapcols!($A, 1,3);
8.107 ns (0 allocations: 0 bytes)
in julia there is the #view macro, that allows you to create an array that is just a reference to another array, for example:
A = [1 2;3 4]
Aview = #view A[:,1] #view of the first column
Aview[1,1] = 10
julia> A
2×2 Array{Int64,2}:
10 2
3 4
with that said, when working with concrete number types (Float64,Int64,etc), julia uses contiguous blocks of memory with the direct representation of the number type. that is, a julia array of numbers is not an array of pointers were each element of an array is a pointer to a value. if the values of an array can be represented by a concrete binary representation (an array of structs, for example) then an array of pointers is used.
I'm not a computer science expert, but i observed that is better to have your data tightly packed that using a lot of pointers when doing number crunching.
Another different case is Sparse Arrays. the basic julia representation of an sparse array is an array of indices and an array of values. here you can simply swap the indices instead of copying the values
I'm new to Julia and wonder what is the best way to get the index of subarray, consider the following array of vectors
vec = [[1, 2, 3], [4, 5, 6]]
I would like to get the index of the element [4, 5, 6], however I can not use getindex(), execution of the following code:
getindex(vec, [1, 2, 3])
gives:
BoundsError: attempt to access 2-element Array{Array{Int64,1},1} at index [[1, 2, 3]]
So I wonder if there are any effective build-in methods for doing this. Of course I can map this array of vectors into another array of numbers and do a search inside new array of numbers, but it isn't really a solution what I expect.
Second question is how do I learn more about search methods in Julia and their performances. I guess the theoretical speed of search scales like \sqrt(N) however depending on the certain method the real code time may vary significantly.
Judging by the name of the function you might be mislead: getindex retrieves the value stored at an index.
If you want to find the index of something in an array you can make use of find* methods findfirst, findall...
julia> vec=[[1,2,3],[4,5,6]]
2-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
julia> i = findfirst(x->x==[4,5,6],vec)
2
julia> vec[i]
3-element Array{Int64,1}:
4
5
6
Concerning your second question:
It's best to inform yourself about search/sort algorithms in general (e.g. https://codeburst.io/algorithms-i-searching-and-sorting-algorithms-56497dbaef20?gi=3bdbf8cbaca0), because the performance depends much more on the chosen algorithm than on the language specific implementation. E.g. time complexity can be very different (O(n), O(log(n),...).
I think you've misunderstood what getindex does. It's the function that gets called by [], so
julia> getindex(vec, 2)
3-element Array{Int64,1}:
4
5
6
All search (or "find") methods in Julia take a function as it's first argument, and find where the function evaluates to true. To find a particular element, use isequal or == (they are equivalent):
julia> findall(==([1,2,3]), vec)
1-element Array{Int64,1}:
1