Let's say I have an array of dimensions declared like this:
integer, dimension(5) :: dims
dims = (/ 5, 6, 7, 8, 9 /)
How can I most simply use this array to allocate another array, using the elements of dims to specify the size of the respective dimensions? Say the second array is declared like this:
real, dimension(:,:,:,:,:), allocatable :: dset
Why can't I do the following?
allocate (dset(dims(:)))
I get Error: Rank mismatch in array reference when I attempt to compile.
I realize that I can do this:
allocate (dset(dims(1), dims(2), dims(3), dims(4), dims(5)))
But I'm looking for something more easily extensible.
You cannot write allocate(dset(dims(:))) for exactly the reason the compiler gives: they have different ranks. If you were to print shape(dims), you would see 5 on-screen; if you were to print shape(dset), you would see either 0 0 0 0 0 or 5 6 7 8 9 (depends if you allocated it or not); dims is a rank-1 array, dset is a rank-5 array.
So pretty much the only way to allocate an allocatable is via the explicit method that you feel is inextensible.
Related
I have to write a code that return all elements from a given list which are strictly greater than a given integer, it returns from left to right. I cannot use recursion or any other function except the built-in functions: append/3, append/2, member/2, select/3, reverse/2, findall/3, bagof/3, setof/3, sumlist/2
Example case:
greater_list([1,9,2,8,3,7,12],7, X).
X = 12 ? ;
X = 8 ? ;
X = 9 ? ;
no
I can write it with recursion or help predicates, but without them I do not know how to start. I could use findall/3 but it would not return element by elements, but a list of elements greater than that given number.
I can write it with recursion or help predicates, but without them I do not know how to start.
I would be interested in how you think you can solve this with helper predicates but not without.
But for starting, consider this: What you need to do is to enumerate certain elements of the list. That is, enumerate elements of the list that have some property.
So to start, you need to know how to enumerate elements of the list. Once you know how to do that, you can worry about the property that they must fulfill.
You can enumerate list elements using member/2:
?- member(X, [1,9,2,8,3,7,12]).
X = 1 ;
X = 9 ;
X = 2 ;
X = 8 ;
X = 3 ;
X = 7 ;
X = 12.
Now, we want to enumerate elements, but only those that fulfill the property X > 7. This is equivalent to saying that "X is a member of the list, and X > 7". In Prolog, (something like) "and" is written with a comma (,):
?- member(X, [1,9,2,8,3,7,12]), X > 7.
X = 9 ;
X = 8 ;
X = 12.
Your predicate is supposed to take a variable limit, not hardcode the limit of 7. This will be similar to:
?- Limit = 7, member(X, [1,9,2,8,3,7,12]), X > Limit.
Limit = 7,
X = 9 ;
Limit = 7,
X = 8 ;
Limit = 7,
X = 12.
Packing this up in a predicate definition will get you started. It looks like the order in which the elements are enumerated here is the reverse of what is intended. Maybe one of your built-ins helps you with this...
(Also, if you know how to write this using findall, you can then use member to enumerate the elements of the findall'ed list. But you shouldn't get in the habit of using findall in general, and especially not if the required solution isn't even a list. Beginners and bad teachers tend to over-emphasize putting things in lists, because that is what you have to do in lesser programming languages. Free yourself from thinking in other languages, even if your teacher can't.)
You can use findall/3 to get a list of the sought elements and then use member/2 to enumerate the members of that list:
greater_list(L,Limit,X) :-
findall(E,(member(E,L),E>Limit),Es),
member(X,Es).
Then:
?- greater_list([1,9,2,8,3,7,12],7, X).
X = 9 ;
X = 8 ;
X = 12.
?- greater_list([],7, X).
false.
And in a roundabout way:
?- findall(X, greater_list([1,9,2,8,3,7,12],7, X), Xs).
Xs = [9, 8, 12].
NB. this relies on recursion, I didn't notice that you couldn't use it at first
Instead of reversing the list, you can write the predicate without other helper predicates and consider first the recursive case. This ensures the first element to be checked against N will be the last element of the list.
greater_list([_|L], N, X) :- greater_list(L,N,X).
greater_list([X|_], N, X) :- X > N.
The lack of a clause for the empty list means that the predicate fails for empty lists.
The first clause above declares that X is item from a list that is greater than N if it is such an item in the sublist L.
The second clause, tried on backtracking, declares that the predicate is also true if X is the front element of the list and it is greater than N.
Both clause make Prolog search first in the sublist, and only when backtracking, consider the values stored in the list. As backtracking unfolds from deeper recursion levels first, the rule will be applied in a way that checks the last element first, then second to last, etc.
[eclipse 2]: greater_list([1,9,2,8,3,7,12],7, X).
X = 12
Yes (0.00s cpu, solution 1, maybe more) ? ;
X = 8
Yes (0.00s cpu, solution 2, maybe more) ? ;
X = 9
Yes (0.00s cpu, solution 3, maybe more) ? ;
No (0.00s cpu)
This doesn't work
program main
implicit none
integer :: nx = 3
integer :: ny = 5
integer :: nz = 8
real, allocatable, dimension(:,:,:) :: A
real, allocatable, dimension(:,:) :: B
allocate(A(nx,0:ny,nz) )
! ...do something with array A and at some point cope a slice of A to B:
B = A(:,:,1)
! in this case B is (1:nx, 1: ny+1)
end program main
The code above automatically allocates B and copies A(:,:,1) to B. However it doesn't keep the lower/upper bound of 0/ny, instead B has its lower bound to 1 and upper bound to ny+1.
The only way I found to keep the lower/upper bound of A 2dn-dim is by explicitly allocate B as:
allocate(B(nx, 0:ny))
B = A(:,:,1)
! in this case B is (1:nx, 0:ny)
Given that I have many more variables than in this simple example, is there a way to assign like B=A(:,:,1) and also keep the bounds of A without explicitly allocating B?
A(:,:,1) is an expression. It has bounds (1:nx, 1:ny), BOTH ranks start at 1. It is not the original array, it is a new expression.
However, even if it was an array that had some other lower bounds, automatic allocation always allocates indexes starting from 1. Basically, the right hand side is an expression again.
For your case you do have to allocate explicitly.
You can use:
allocate(B(lbound(A,1):ubound(A,1), lbound(A,2):ubound(A,2)))
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
Let's say I have an NTuple with 4 entries of Int64 uninitiallized. How do I set the value of each index separately?
I tried the setindex function of base but it didn't work. Any idea?
T = NTuple{4,Int64}
setindex(T,9,2) # set T(2) to 9
You probably meant NTuple{4, Int64} not Ntuple{4, Int64}.
NTuple is a compact way of representing the type tuples having elements of a single type (not actual values but their types; the thing that might be confusing here is that NTuple{4, Int64} is also technically a value that you can bind to a variable, but this is not what you probably want to do given your question).
You can check this by looking up help on it. In your case it represents a type for a tuple of length 4 and all elements of type Int64. For example (1,2,3,4) is such a tuple. You can check it by writing (1,2,3,4) isa NTuple{4, Int64} which will evaluate to true.
Now if you ask why a tuple like (1,2,3,4) does not support setindex! the reason is that tuples are immutable in Julia, see https://docs.julialang.org/en/latest/manual/types/#Tuple-Types-1. This means that you have to assign a value to each field of a tuple upon its construction and it cannot be mutated.
If you want a mutable container you should probably consider using a vector instead of a tuple. For example:
julia> x = Vector{Int}(undef, 4)
4-element Array{Int64,1}:
0
0
0
0
julia> x[2] = 9
9
julia> x
4-element Array{Int64,1}:
0
9
0
0
In Matlab I can write:
[0:n]
to get an array (1,n). For n=2, I get:
0 1 2
How to do the same in Julia? The purpose is to get the same type of array (1,3).
I know I can write [0 1 2], but I want something general like in Matlab.
In julia, the colon operator (in this context, anyway) returns a UnitRange object. This is an iterable object; that means you can use it with a for loop, or you can collect all its contents, etc. If you collect its contents, what you get here is a Vector.
If what you're after is explicitly a RowVector, then you can collect the contents of the UnitRange, and reshape the resulting vector accordingly (which in this case can be done via a simple transpose operation).
julia> collect(1:3).'
1×3 RowVector{Int64,Array{Int64,1}}:
1 2 3
The .' transpose operator is also defined for UnitRange arguments:
julia> (1:3).'
1×3 RowVector{Int64,UnitRange{Int64}}:
1 2 3
However, note the difference in the resulting type; if you apply .' again, you get a UnitRange object back again.
If you don't particularly like having a "RowVector" object, and want a straightforward array, use that in an Array constructor:
julia> Array((1:3).')
1×3 Array{Int64,2}:
1 2 3
(above as of latest julia 0.7 dev version)