Iterate through multiple variables (or whole matrix) in Julia - arrays

I have a 5 dimensional array want to do a calculation for each field and depending on the result fill each field either with 'true' or 'false'. Now I am wondering if there is a fast way of doing so without using 5 'nested' loops.
Thanks for your help
Edit:
Sorry that the question wasn't clear. I need to do calculations with 5 different variables and I have check each possible combination.
My current approach is this:
while i<10
while j<10
while k < 10
while l<10
while m <10
#some calculation which returns true or false
A[i,j,k,l,m]=f(i, j, k, l, m);
m+=1;
end
l+=1;
end
k +=1;
end
j+=1;
end
i+=1;
end
where A is my array. Now I am wondering if there is a more efficient way of doing this.
Sorry, I hope it is more clarified now.

You can use CartesianIndices function for example like this:
julia> x = Array{Tuple}(undef, 2,2,2,2,2);
julia> for idx in CartesianIndices(x)
x[idx] = Tuple(idx)
end
julia> x
2×2×2×2×2 Array{Tuple,5}:
[:, :, 1, 1, 1] =
(1, 1, 1, 1, 1) (1, 2, 1, 1, 1)
(2, 1, 1, 1, 1) (2, 2, 1, 1, 1)
[:, :, 2, 1, 1] =
(1, 1, 2, 1, 1) (1, 2, 2, 1, 1)
(2, 1, 2, 1, 1) (2, 2, 2, 1, 1)
[:, :, 1, 2, 1] =
(1, 1, 1, 2, 1) (1, 2, 1, 2, 1)
(2, 1, 1, 2, 1) (2, 2, 1, 2, 1)
[:, :, 2, 2, 1] =
(1, 1, 2, 2, 1) (1, 2, 2, 2, 1)
(2, 1, 2, 2, 1) (2, 2, 2, 2, 1)
[:, :, 1, 1, 2] =
(1, 1, 1, 1, 2) (1, 2, 1, 1, 2)
(2, 1, 1, 1, 2) (2, 2, 1, 1, 2)
[:, :, 2, 1, 2] =
(1, 1, 2, 1, 2) (1, 2, 2, 1, 2)
(2, 1, 2, 1, 2) (2, 2, 2, 1, 2)
[:, :, 1, 2, 2] =
(1, 1, 1, 2, 2) (1, 2, 1, 2, 2)
(2, 1, 1, 2, 2) (2, 2, 1, 2, 2)
[:, :, 2, 2, 2] =
(1, 1, 2, 2, 2) (1, 2, 2, 2, 2)
(2, 1, 2, 2, 2) (2, 2, 2, 2, 2)
The code stores in an entry `x[a,b,c,d,e]` a tuple `(a,b,c,d,e)`.

You can do the same kind of operations as you'd do on a 1-Dimensional matrix.
julia> A = rand(4,4,4,4,4);^C
julia> for (i, v) in enumerate(A)
if v > 0.5
A[i] = 0
end
end
Also, somthing like:
julia>map!(x->x>.5, A, A)
Also if the original Array is of some type other than Bool I'd suggest you use a different matrix to assign the result values for type stability.

Related

How to get the mean of specific values from an nd.array region?

Given an ndarray:
np.array(
(
(1, 2, 3, 3, 2),
(4, 5, 4, 3, 2),
(1, 1, 1, 1, 1),
(0, 0, 0, 0, 0),
(0, 2, 3, 4, 0),
)
)
extract the mean of the values bounded by a rectangle with coordinates: (1, 1), (3, 1), (1, 3), (3, 3).
The extracted region of the array would be:
5, 4, 3,
1, 1, 1,
0, 0, 0,
And the mean would be ~1.666666667
import numpy as np
arr = np.array(
(
(1, 2, 3, 3, 2),
(4, 5, 4, 3, 2),
(1, 1, 1, 1, 1),
(0, 0, 0, 0, 0),
(0, 2, 3, 4, 0),
)
)
mean = arr[1:4, 1:4].mean()

Paradigms for constructing permutations explained

According to the Algorithm Design Manual Sec 14.4, there are two paradigms to constructing permutations:
Ranking/Unranking
Incremental Change
I'm not grasping the section and I would appreciate an alternative explanation. Can you elaborate on the two with examples?
Ranking/Unranking
A particular ranking of a permutation associates an integer with a particular ordering of all the permutations of a set of distinct items. For our purposes the ranking will assign integers 0..(n!-1) to an ordering of all the permutations of the integers 0..(n-1).
Rank({2, 1, 0, 3}) = 17
Unranking is the inverse process: given a rank r obtain the permutation.
Unrank(17) = {2, 1, 0, 3}
Therefore, rank and unrank functions must be inverses of each other, that is, there exists a bijection.
permutation p = Unrank(Rank(p), n)
For example, the permutations of the digits zero to 3 arranged lexicographically have the following rank:
PERMUTATION RANK
(0, 1, 2, 3) -> 0
(0, 1, 3, 2) -> 1
(0, 2, 1, 3) -> 2
(0, 2, 3, 1) -> 3
(0, 3, 1, 2) -> 4
(0, 3, 2, 1) -> 5
(1, 0, 2, 3) -> 6
(1, 0, 3, 2) -> 7
(1, 2, 0, 3) -> 8
(1, 2, 3, 0) -> 9
(1, 3, 0, 2) -> 10
(1, 3, 2, 0) -> 11
(2, 0, 1, 3) -> 12
(2, 0, 3, 1) -> 13
(2, 1, 0, 3) -> 14
(2, 1, 3, 0) -> 15
(2, 3, 0, 1) -> 16
(2, 3, 1, 0) -> 17
(3, 0, 1, 2) -> 18
(3, 0, 2, 1) -> 19
(3, 1, 0, 2) -> 20
(3, 1, 2, 0) -> 21
(3, 2, 0, 1) -> 22
(3, 2, 1, 0) -> 23
Incremental Change
Incremental change methods work by defining the next and previous operations to transform one permutation into another, typically by swapping two elements. The tricky part is to schedule the swaps so that permutations do not repeat until all of them have been generated. The output picture below gives an ordering of the six permutations of {1,2,3} using a single swap between successive permutations.
References
https://rosettacode.org/wiki/Permutations/Rank_of_a_permutation
https://en.wikipedia.org/wiki/Factorial_number_system#Permutations
https://computationalcombinatorics.wordpress.com/2012/09/10/ranking-and-unranking-of-combinations-and-permutations/

Ruby multi dimensional arrays and user defined function

I have many multiple dimensional arrays. A simplified example:
t0 = [2, 1, 3, 2, 2, 2, 2, 1, 2, 3]
t1 = [1, 2, 1, 3, 2, 2, 2, 2, 1, 2]
t2 = [2, 1, 3, 2, 2, 2, 2, 1, 2, 3]
t3 = [2, 1, 1, 3, 1, 4, 2, 2, 1, 2]
t4 = [2, 1, 3, 1, 2, 2, 2, 2, 1, 2]
t = [t0,t1,t2,t3,t4]
instance1= [t]
Each cell is processed. For each cell the 8 ajoining cells (think terrain map) plus the equivalent cells in several other arrays are accessed and updated. For example:
for h in 1..3
for i in 1..8
if instance1[0][i][h] == 4 # burning
if instance1[0][i-1][h-1] > 0 && instance1[0][i-1][h-1] < 4
# check probability
probability = Fernandes1(moisturex[0][i-1][h-1], windspeed, temperature, fueltypex[0][i-1][h-1])
if probability > 0.5
instance2[0][i-1][h-1] = 4 # now burning
end
end
if instance1[0][i-1][h] > 1 && instance1[0][i-1][h] < 4
# check probability
...................................
I would like to perform this processing in a user defined function. I guess the alternative to globals is to pass all variables as function parameters but that would be very tedious and error prone - there being so many.
Is the best approach to declare the arrays as global?
$t0 = [2, 1, 3, 2, 2, 2, 2, 1, 2, 3]
$t1 = [1, 2, 1, 3, 2, 2, 2, 2, 1, 2]
$t2 = [2, 1, 3, 2, 2, 2, 2, 1, 2, 3]
$t3 = [2, 1, 1, 3, 1, 4, 2, 2, 1, 2]
$t4 = [2, 1, 3, 1, 2, 2, 2, 2, 1, 2]
$t = [$t0,$t1,$t2,$t3,$t4]
$instance1= [$t]
And as here, do I need to define all the sub arrays as globals or just the ones that I directly reference in the user defined function? Or by defining the outer array (i.e. $instance1) as global do the sub arrays become global?
Any guidance much appreciated
OK defining just the globals that are referenced seems to work fine (e.g. the outer array but not the sub-arrays. I guess the only overhead of Globals is sustained use of memory.
But I'm wondering if there is a more Rubiesque way to go.

Create an array containing values oscillating between two boundaries

I am wondering if there is a way to generate an array which, for example, would start from 0, increase by 1 until it reaches 3, and then decreases by 1 until it reaches 0 again, eg
[0,1,2,3,2,1,0]
and if I could specify the number of values in the array ahead of time, that would be great. For example, if I could set the lower bound(0), upper bound (3), increment(1), and length of array (9):
[].oscillate(0,3,1,9) would give me this:
[0,1,2,3,2,1,0,1,2]
As of now, the best thing I can come up with is this:
values = []
until values.count >= 9
values.pop
x=0
values << x && x+=1 while x < 3
values << x && x-=1 while x >= 0
end
Fun exercise!
You're looking for a triangle wave.
The formulas on Wikipedia are for the standard shape (between -1 and 1), but here's an adapted version for any wave position, period and amplitude :
def triangle_wave(min, max, increment, length, offset = 0)
amplitude = max - min
period = 2 * amplitude
Array.new(length) do |i|
min + ((increment * (i + offset) - amplitude) % period - amplitude).abs
end
end
puts triangle_wave(0, 3, 1, 9) == [0, 1, 2, 3, 2, 1, 0, 1, 2]
# true
p triangle_wave(-3, 3, 1, 20)
# => [-3, -2, -1, 0, 1, 2, 3, 2, 1, 0, -1, -2, -3, -2, -1, 0, 1, 2, 3, 2]
p triangle_wave(5, 9, 2, 9)
# => [5, 7, 9, 7, 5, 7, 9, 7, 5]
p triangle_wave(0, 1, 0.25, 9)
# => [0.0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0.0]
p triangle_wave(-3, 0, 1, 9, 3)
# => [0, -1, -2, -3, -2, -1, 0, -1, -2]
p triangle_wave(0, 1, 1, 9)
# => [0, 1, 0, 1, 0, 1, 0, 1, 0]
min should be lower than max, increment should be positive and max-min should be divisible by increment. Those are restrictions on the input but not on the output : any wave can be generated.
This problem could be a textbook example of the use of Ruby's flip-flop operator.
As the question only makes sense when there is a non-negative integer steps such that high = low + steps * increment, I've replaced the method's argument high with steps.
def oscillate(low, steps, increment, length)
high = low + steps * increment
n = low
length.times.each_with_object([]) do |_,a|
a << n
n += (n==low)..(n==high-increment) ? increment : -increment
end
end
oscillate(0,3,1,9)
#=> [0, 1, 2, 3, 2, 1, 0, 1, 2]
oscillate(-1, 4, 2, 16)
#=> [-1, 1, 3, 5, 7, 5, 3, 1, -1, 1, 3, 5, 7, 5, 3, 1]
To show what's happening here I will modify the code a little and add some puts statements, then run it with the first example.
def oscillate(low, steps, increment, length)
high = low + steps * increment
puts "high = #{high}"
n = low
length.times.each_with_object([]) do |_,a|
a << n
diff = (n==low)..(n==high-increment) ? increment : -increment
print "n=#{n}, a<<n=#{a}, diff=#{diff}, "
n += diff
puts "n+=diff=#{n}"
end
end
oscillate(0,3,1,9)
high = 3
n=0, a<<n=[0], diff= 1, n+=diff=1
n=1, a<<n=[0, 1], diff= 1, n+=diff=2
n=2, a<<n=[0, 1, 2], diff= 1, n+=diff=3
n=3, a<<n=[0, 1, 2, 3], diff=-1, n+=diff=2
n=2, a<<n=[0, 1, 2, 3, 2], diff=-1, n+=diff=1
n=1, a<<n=[0, 1, 2, 3, 2, 1], diff=-1, n+=diff=0
n=0, a<<n=[0, 1, 2, 3, 2, 1, 0], diff= 1, n+=diff=1
n=1, a<<n=[0, 1, 2, 3, 2, 1, 0, 1], diff= 1, n+=diff=2
n=2, a<<n=[0, 1, 2, 3, 2, 1, 0, 1, 2], diff= 1, n+=diff=3
#=> [0, 1, 2, 3, 2, 1, 0, 1, 2]
Try this
def oscillate(a, b, step, num)
ramp_up = a.step(b, step).entries
ramp_down = ramp_up.drop(1).reverse.drop(1)
ramp_up.concat(ramp_down).cycle.take(num)
end
How does this work?
creates the ramp_up and ramp_down arrays
concatenates the two arrays
cycle returns an ever-repeating enumerator
take materializes num elements from that enumerator. Other than suggested in a comment, this does not recalculate anything. It just materializes entries from the enumerator.

Finding recurrence relation and complexity

Based on the number of operations, finding out the recurrence relation!
a = N;
var = 0;
while (a > 1)
{
var = var + a;
num = 2 * var;
a = a / 2;
}
I think that the the recurrence relaton that will be formed is: (Assignment operations are to be not counted)
T(n)= (from a=1 to N)Σ(3)
Am I right??
Now using this recurrence relation, how to find its complexity.
What you want to do is find how many times this operation is called, so consider this: after each call a is divided by 2, so if M = N/2 then T(M) = T(N) - 1.
Now, each iteration of this loop divides N again so you get the following:
T(N) = T(N/2) + 1 = ... = k + T(N/(2^k))
The stop condition is this: a>1 so you need to check when N/(2^k) <= 1
N/2^k = 1 -> log (n) = k
So T(N) = log(n) + T(1) = log(n)
This is the answer in 'big O' notation.
Empirical approach:
First reduce the "educational noise" from the code by simplifying it and add an iteration counter (c). Then look at the result (N,count) and after a while you see, that 2 ^ count = N for all N in [1,2,4,8,16,..].
So the complexity Compl(loop) = O(log_2(N)).
let rec loop a c =
match a with
| x when x > 1 ->
let a1 = a / 2
loop a1 (c+1)
| _ -> (a,c)
// after staring at the result of the computation we came up with this theory:
let theory n = int (System.Math.Log10(float n) / System.Math.Log10(2.0))
[1..64]
|> List.map (fun a -> a,loop a 0, theory a)
|> List.map (fun (a0,(a,c),aa) -> a0,c,aa)
Data:
[(1, 0, 0); (2, 1, 1); (3, 1, 1); (4, 2, 2); (5, 2, 2); (6, 2, 2); (7, 2, 2);
(8, 3, 3); (9, 3, 3); (10, 3, 3); (11, 3, 3); (12, 3, 3); (13, 3, 3);
(14, 3, 3); (15, 3, 3); (16, 4, 4); (17, 4, 4); (18, 4, 4); (19, 4, 4);
(20, 4, 4); (21, 4, 4); (22, 4, 4); (23, 4, 4); (24, 4, 4); (25, 4, 4);
(26, 4, 4); (27, 4, 4); (28, 4, 4); (29, 4, 4); (30, 4, 4); (31, 4, 4);
(32, 5, 5); (33, 5, 5); (34, 5, 5); (35, 5, 5); (36, 5, 5); (37, 5, 5);
(38, 5, 5); (39, 5, 5); (40, 5, 5); (41, 5, 5); (42, 5, 5); (43, 5, 5);
(44, 5, 5); (45, 5, 5); (46, 5, 5); (47, 5, 5); (48, 5, 5); (49, 5, 5);
(50, 5, 5); (51, 5, 5); (52, 5, 5); (53, 5, 5); (54, 5, 5); (55, 5, 5);
(56, 5, 5); (57, 5, 5); (58, 5, 5); (59, 5, 5); (60, 5, 5); (61, 5, 5);
(62, 5, 5); (63, 5, 5); (64, 6, 6)]
The recurrence relation is:
T(1) = a
T(n) = b + T(n/2)
The first part comes from the case where the loop variable equals 1, in which case only the comparison at the top of the loop executes. The second line comes from the constant amount of work done in the loop body, b, plus the time to execute the loop with the updated loop variable value.
The first few terms are:
n T
1 a
2 a + b
4 a + 2b
8 a + 3b
Based on this we can guess the general form:
T(n) = a + b log n
Proving that is left as an exercise; but you can just plug it in to the recurrence relation to see that it satisfies the requirements.
The asymptotic complexity is logarithmic.

Resources