Append to a CartesianIndex - julia

How do I append to a CartesianIndex? Example:
index = CartesianIndex(3,3)
append!(index, 1)
# Desired output -> CartesianIndex(3, 3, 1)
I can do this in a roundabout way converting the index to a tuple, adding the 1, and then converting back. However, is there a better way?

CartesianIndexes are immutable, so you can't modify! them in-place. Instead, just create a new one based on the existing one:
julia> index = CartesianIndex(3,3)
CartesianIndex(3, 3)
julia> CartesianIndex(index, 1)
CartesianIndex(3, 3, 1)

Related

How to iterate over whole array when I need i, j, k?

Given A is a multi-dimensional array, can I collapse iteration through every element into one for statement if I need i,j,k,etc.? In other words, I am looking for a more compact version of the following:
for k in 1:size(A,3)
for j in 1:size(A,2)
for i in 1:size(A,1)
# Do something with A[i+1,j,k], A[i,j+1,k], A[i,j,k+1], etc.
end
end
end
I think the solution is with axes or CartesianIndices, but I can't get the syntax right. Failed attempts:
julia> for (i,j,k) in axes(A)
println(i)
end
1
1
1
julia> for (i,j,k) in CartesianIndices(A)
println(i)
end
ERROR: iteration is deliberately unsupported for CartesianIndex. Use `I` rather than `I...`, or use `Tuple(I)...`
It would be great if in addition to a solution which defines i,j,k, you could also provide a solution that works regardless of the number of dimensions in A.
You are almost there. Read the message carefully:
ERROR: iteration is deliberately unsupported for CartesianIndex.
It is the "pattern matching" in (i,j,k) in CartesianIndices(...) that fails, not the approach in general (I made the same mistake when reproducing the problem!). You have to convert the individual CartesianIndexes to tuples first:
julia> for ix in CartesianIndices(A)
println(Tuple(ix))
end
(1, 1, 1)
(2, 1, 1)
(3, 1, 1)
(1, 2, 1)
(2, 2, 1)
(3, 2, 1)
...
or using axes:
for (i,j,k) in Iterators.product(axes(x)...)
println([i,j,k]) # or whatever else you want
end

How do I calculate a scalar product in a sympy vector?

Pretty simple question:
from sympy.vector import Vector
v = Vector(0, 2, 1)
print(2*v)
Output expected:
Vector(0, 4, 2)
I'm unable to find how to do this, the docs do not talk about scalar product.
Matrix understands scalar multiplication but not Vector. So either convert back and forth between Matrix and Vector, file a feature request and wait for a possible enhancement, or write your own __mul__ and __rmul__ routine (part of the beauty of Python):
>>> v.func(*Matrix(v.args)*2)
Vector(0, 4, 2)
>>> Vector.__rmul__ = Vector.__mul__ = lambda s,o: s.func(*[i*o for i in s.args])
>>> 2*v
Vector(0, 4, 2)
>>> v*2
Vector(0, 4, 2)
I think the expected way to work with vectors is to create a coordinate system and use its i, j, k basis:
In [32]: from sympy.vector import CoordSys3D
In [33]: N = CoordSys3D('N')
In [34]: v = 2*N.j + N.k
In [35]: v
Out[35]: 2*N.j + N.k
In [36]: 2*v
Out[36]: 4*N.j + 2*N.k

Understand Function capturing through map and reduce

I 'am beginner in Elixir language , so In the blow example
iex> Enum.reduce([1, 2, 3], 0, &+/2)
6
iex> Enum.map([1, 2, 3], &(&1 * 2))
[2, 4, 6]
In the reduce method I understand that we capture the second arg and we add to it the list values until we reach the end of the List .
but in the map method I can't understand how the capturing works?
reference
http://elixir-lang.org/getting-started/recursion.html
map/2 and reduce/2 are two different functions.
map/2 takes some values and a function that takes a single value and applies that function to each element in the collection, effectively transforming it into a list.
reduce/2 takes some values and a function that takes 2 arguments. The first argument of that function is the element in your collection, while the second is an accumulator. So the function reduces your collection down to a single value.
Using the syntax &+/2, this does not capture the second argument. It calls the + function on the two arguments. The /2 is to denote that it has an arity of 2 (it takes 2 arguments). Take the following code as an example.
iex(1)> fun = &+/2
&:erlang.+/2
iex(2)> fun.(1,2)
3
Here, we set the + function to the variable fun. We can then apply that function to our arguments in order to get a value.
The other syntax &(&1 * 2) creates an anonymous function that takes our one and only argument (represented by &1) and multiplies it by 2. The initial & just means that it is an anonymous function.
iex(3)> fun2 = &(&1 * 2)
#Function<6.118419387/1 in :erl_eval.expr/5>
iex(4)> fun2.(5)
10
They are similar concepts, but slightly different.
Basically:
map returns you new list as a result of applying function on each element of the list
reduce returns you result of the computation of applied function over the list - you reduced the whole collection into (most likely) one result eg. integer
In your example:
iex> Enum.reduce([1, 2, 3], 0, &+/2)
# it equals:
0 + 1 # first step, 1 is out of the list now
1 + 2 # second step, 2 is out of the list now
3 + 3 # last step, 3 is out of the list now, return 6
iex> Enum.map([1, 2, 3], &(&1 * 2))
[2, 4, 6]
# apply for each element function fn(x) -> 2 * x end, but with syntactic sugar
There are three different ways to express an anonymous function, when passing it as an argument:
Enum.reduce([1, 2, 3], 0, fn p1, p2 -> p1 + p2 end)
or, using a shorthand and enumerated params:
Enum.reduce([1, 2, 3], 0, &(&1 + &2))
or, explicitly naming the function of the respective arity (2 for reduce, because reduce expects a function of arity 2):
Enum.reduce([1, 2, 3], 0, &+/2)
The latter, while looking cumbersome, is just a common way to write a function name with it’s arity. Kernel.+/2 is a function name here. If you were using your own function as the reducer:
defmodule My, do: def plus(p1, p2), do: p1 + p2
Enum.reduce([1, 2, 3], 0, &My.plus/2)
All three ways described above are 100% equivalent.
JIC: For the mapper those three ways would be:
Enum.map([1, 2, 3], fn p -> p * 2 end)
Enum.map([1, 2, 3], &(&1 * 2))
—
The third notation is not available here, since there is no such a function, that takes a number and returns it’s doubled value. But one might declare her own:
defmodule Arith, do: def dbl(p1), do: p1 * 2
Enum.map([1, 2, 3], &Arith.dbl/1) # map expects arity 1
#⇒ [2, 4, 6]

How to make recursive nested loops which use loop variables inside?

I need to make a nested loop with an arbitrary depth. Recursive loops seem the right way, but I don't know how to use the loop variables in side the loop. For example, once I specify the depth to 3, it should work like
count = 1
for i=1, Nmax-2
for j=i+1, Nmax-1
for k=j+1,Nmax
function(i,j,k,0,0,0,0....) // a function having Nmax arguments
count += 1
end
end
end
I want to make a subroutine which takes the depth of the loops as an argument.
UPDATE:
I implemented the scheme proposed by Zoltan. I wrote it in python for simplicity.
count = 0;
def f(CurrentDepth, ArgSoFar, MaxDepth, Nmax):
global count;
if CurrentDepth > MaxDepth:
count += 1;
print count, ArgSoFar;
else:
if CurrentDepth == 1:
for i in range(1, Nmax + 2 - MaxDepth):
NewArgs = ArgSoFar;
NewArgs[1-1] = i;
f(2, NewArgs, MaxDepth, Nmax);
else:
for i in range(ArgSoFar[CurrentDepth-1-1] + 1, Nmax + CurrentDepth - MaxDepth +1):
NewArgs = ArgSoFar;
NewArgs[CurrentDepth-1] = i;
f(CurrentDepth + 1, NewArgs, MaxDepth, Nmax);
f(1,[0,0,0,0,0],3,5)
and the results are
1 [1, 2, 3, 0, 0]
2 [1, 2, 4, 0, 0]
3 [1, 2, 5, 0, 0]
4 [1, 3, 4, 0, 0]
5 [1, 3, 5, 0, 0]
6 [1, 4, 5, 0, 0]
7 [2, 3, 4, 0, 0]
8 [2, 3, 5, 0, 0]
9 [2, 4, 5, 0, 0]
10 [3, 4, 5, 0, 0]
There may be a better way to do this, but so far this one works fine. It seems easy to do this in fortran. Thank you so much for your help!!!
Here's one way you could do what you want. This is pseudo-code, I haven't written enough to compile and test it but you should get the picture.
Define a function, let's call it fun1 which takes inter alia an integer array argument, perhaps like this
<type> function fun1(indices, other_arguments)
integer, dimension(:), intent(in) :: indices
...
which you might call like this
fun1([4,5,6],...)
and the interpretation of this is that the function is to use a loop-nest 3 levels deep like this:
do ix = 1,4
do jx = 1,5
do kx = 1,6
...
Of course, you can't write a loop nest whose depth is determined at run-time (not in Fortran anyway) so you would flatten this into a single loop along the lines of
do ix = 1, product(indices)
If you need the values of the individual indices inside the loop you'll need to unflatten the linearised index. Note that all you are doing is writing the code to transform array indices from N-D into 1-D and vice versa; this is what the compiler does for you when you can specify the rank of an array at compile time. If the inner loops aren't to run over the whole range of the indices you'll have to do something more complicated, careful coding required but not difficult.
Depending on what you are actually trying to do this may or may not be either a good or even satisfactory approach. If you are trying to write a function to compute a value at each element in an array whose rank is not known when you write the function then the preceding suggestion is dead flat wrong, in this case you would want to write an elemental function. Update your question if you want further information.
you can define your function to have a List argument, which is initially empty
void f(int num,List argumentsSoFar){
// call f() for num+1..Nmax
for(i = num+1 ; i < Nmax ; i++){
List newArgs=argumentsSoFar.clone();
newArgs.add(i);
f(i,newArgs);
}
if (num+1==Nmax){
// do the work with your argument list...i think you wanted to arrive here ;)
}
}
caveat: the stack should be able to handle Nmax depth function calls
Yet another way to achieve what you desire is based on the answer by High Performance Mark, but can be made more general:
subroutine nestedLoop(indicesIn)
! Input indices, of arbitrary rank
integer,dimension(:),intent(in) :: indicesIn
! Internal indices, here set to length 5 for brevity, but set as many as you'd like
integer,dimension(5) :: indices = 0
integer :: i1,i2,i3,i4,i5
indices(1:size(indicesIn)) = indicesIn
do i1 = 0,indices(1)
do i2 = 0,indices(2)
do i3 = 0,indices(3)
do i4 = 0,indices(4)
do i5 = 0,indices(5)
! Do calculations here:
! myFunc(i1,i2,i3,i4,i5)
enddo
enddo
enddo
enddo
enddo
endsubroutine nestedLoop
You now have nested loops explicitly coded, but these are 1-trip loops unless otherwise desired. Note that if you intend to construct arrays of rank that depends on the nested loop depth, you can go up to rank of 7, or 15 if you have a compiler that supports it (Fortran 2008). You can now try:
call nestedLoop([1])
call nestedLoop([2,3])
call nestedLoop([1,2,3,2,1])
You can modify this routine to your liking and desired applicability, add exception handling etc.
From an OOP approach, each loop could be represented by a "Loop" object - this object would have the ability to be constructed while containing another instance of itself. You could then theoretically nest these as deep as you need to.
Loop1 would execute Loop2 would execute Loop3.. and onwards.

Indexing an array with a tuple

Suppose I have a tuple of (1, 2, 3) and want to index a multidimensional array with it such as:
index = (1, 2, 3)
table[index] = 42 # behaves like table[1][2][3]
index has an unknown number of dimensions, so I can't do:
table[index[0]][index[1]][index[2]]
I know I could do something like this:
functools.reduce(lambda x, y: x[y], index, table)
but it's utterly ugly (and maybe also inefficient), so I wonder if there's a better, more Pythonic choice.
EDIT: Maybe a simple loop is best choice:
elem = table
for i in index:
elem = elem[i]
EDIT2: Actually, there's a problem with both solutions: I can't assign a value to the indexed array :-(, back to ugly:
elem = table
for i in index[:-1]:
elem = elem[i]
elem[index[-1]] = 42
The question is very interesting and also your suggested solution looks good (havn't checked it, but this kind of problem requires a recursive treatment and you just did it in one line).
However, the pythonic way I use in my programs is to use dictionaries of tuples. The syntax is array-like, the performance - of a dictionary, and there was no problem in it for me.
For example:
a = {(1, 2, 3): 'A', (3, 4, 5): 'B', (5, 6, 7, 8): 'C'}
print a[1, 2, 3]
print a[5, 6, 7, 8]
Will output:
A
B
And assigning to an index is super easy:
a[1, 4, 5] = 42. (But you might want to first check that (1, 4, 5) is within the dict, or else it will be created by the assignment)

Resources