how can i separate between two arrays inside a parent array - julia

this code is a small example of what i want to do, i have this small example right here:
y=[[[1,0],[0,0],[1,1],[1,0],[1,0],[0,1]],[[1,0],[0,0],[1,1],[0,0]],[[1,0],[0,0],[1,1],[1,0],[1,0],[1,0]]]
array=[]
all_array=[]
for i in 1:length(y)
for j in 1: length(y[i])
if y[i][j]==[1,0]
push!(array,y[i][j])
end
end
end
what i'm expecting when you return array is this :
[[[1,0],[1,0],[1,0]],[[1,0]],[[1,0],[1,0],[1,0],[1,0]]]
which is 3-element Array{Array{Array{Int64,1},1},1}
but instead i get this:
8-element Array{Any,1}:
[1, 0]
[1, 0]
[1, 0]
[1, 0]
[1, 0]
[1, 0]
[1, 0]
[1, 0]
i don't know what i'm missing here.

You are pushing all the elements that satisfy your condition one after another in array. You could create your array instead like:
julia> array=[[],[],[]]
And modify your loop to push! into each subarray array[i] like this:
julia> for i in 1:length(y)
for j in 1: length(y[i])
if y[i][j]==[1,0]
push!(array[i],y[i][j])
end
end
end
Which then gives you your desired array.
julia> array
3-element Array{Array{Any,1},1}:
[[1, 0], [1, 0], [1, 0]]
[[1, 0]]
[[1, 0], [1, 0], [1, 0], [1, 0]]

Related

Julia JuMP: define a multidimensional variable when a dimension depends on other dimension

While I am defining a linear programming variables, I have to consider
index_i = 1:3 index_j = J = [1:2, 1:5, 1:3]
I want to define a variable x indexed with both i and j such that i is {1,2,3} and j is in {1,2} if i is 1, {1,2,3,4,5} if i is 2 and {1,2,3} if i is 3.
I tried several syntaxes but non of them delivered it successfully. Any suggestion?
I wonder why this is not working
#variable(m, e[i for i in I, j for j in J[i]])
I m expecting a result like this
e[1,1]
e[1,2]
e[1,3]
e[2,1]
e[2,2]
e[2,3]
e[2,4]
e[2,5]
e[3,1]
e[3,2]
e[3,3]
Assuming I=1:3 and J=[1:2, 1:5, 1:3]
you can do:
julia> #variable(m, e[i in I, j in J[i]])
JuMP.Containers.SparseAxisArray{VariableRef, 2, Tuple{Int64, Int64}} with 10 entries:
[1, 1] = e[1,1]
[1, 2] = e[1,2]
[2, 1] = e[2,1]
[2, 2] = e[2,2]
[2, 3] = e[2,3]
[2, 4] = e[2,4]
[2, 5] = e[2,5]
[3, 1] = e[3,1]
[3, 2] = e[3,2]
[3, 3] = e[3,3]

Conditional assignment syntax for array of vectors

I'm new to Julia, coming more from Matlab and Python.
I cannot understand the Julia Syntax for conditional assignment of an array of vectors. To me, it appears to be inconsistent with the conditional assignment of an array of numbers.
For an array of numbers I can do the following:
a = [1,2,3]
b = [0,1,1]
a[b.>0] .= 5
This replaces the two elements of a with the new value 5.
My actual working example is with an array with elements of type Array{Int64,1}:
a = [[1,0,0], [0,1,0], [0,0,1]]
b = [0,1,1]
a[b.>0] .= Int64[0,0,5]
This does not work, output is:
ERROR: DimensionMismatch("array could not be broadcast to match destination")
However, this line works:
a[b.>0] .= [Int64[0,0,5]]
I cant understand this, as the element-wise assignment (.=) makes even less sense to me in the latter case, as the two arrays on the left and right have different sizes.
Can someone give an explanation?
Thanks in advance.
The operation:
x .= y
tries to iterate over x and y and performs the assignment. A simple case is:
julia> x = [1,2,3,4]
4-element Array{Int64,1}:
1
2
3
4
julia> y = [12,14]
2-element Array{Int64,1}:
12
14
julia> x[[2,4]] .= y
2-element view(::Array{Int64,1}, [2, 4]) with eltype Int64:
12
14
julia> x
4-element Array{Int64,1}:
1
12
3
14
We see that the left and right hand side have 2 elements so that an in-place assignment can be performed.
Then Julia has a special rule that if a container in right hand side has length 1 it can be expanded to match the size of the left hand side (this also works in higher dimensions than 1, but let us focus on a simple case).
You you for example have:
julia> x = [1,2,3,4]
4-element Array{Int64,1}:
1
2
3
4
julia> x[[2,4]] .= 11
2-element view(::Array{Int64,1}, [2, 4]) with eltype Int64:
11
11
julia> x
4-element Array{Int64,1}:
1
11
3
11
julia> length(11)
1
julia> x[[2,4]] .= [11]
2-element view(::Array{Int64,1}, [2, 4]) with eltype Int64:
11
11
julia> x
4-element Array{Int64,1}:
1
11
3
11
julia> length([1])
1
A crucial thing to note here is that [1] and 1 behave exactly the same in this case as a number is considered like a 1-element container holding this number in broadcasting.
Now going to your examples:
a = [[1,0,0], [0,1,0], [0,0,1]]
b = [0,1,1]
a[b.>0] .= Int64[0,0,5]
fails because:
julia> length(a[b.>0])
2
julia> length(Int64[0,0,5])
3
and we see that the dimensions do not match.
However in:
a[b.>0] .= [Int64[0,0,5]]
you have:
julia> length([Int64[0,0,5]])
1
So a container having length one gets expanded.
Note, however, that most likely you do not want to do a[b.>0] .= [Int64[0,0,5]] assignment as then a will hold the same array Int64[0,0,5]. E.g.
julia> a = [[1,0,0], [0,1,0], [0,0,1]]
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]
julia> b = [0,1,1]
3-element Array{Int64,1}:
0
1
1
julia> a[b.>0] .= [Int64[0,0,5]]
2-element view(::Array{Array{Int64,1},1}, [2, 3]) with eltype Array{Int64,1}:
[0, 0, 5]
[0, 0, 5]
julia> a
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[0, 0, 5]
[0, 0, 5]
julia> a[2][1] = 100
100
julia> a
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[100, 0, 5]
[100, 0, 5]
and in most cases this is not what you want. A safer approach would be do to for example a for loop like this:
julia> a = [[1,0,0], [0,1,0], [0,0,1]]
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]
julia> b = [0,1,1]
3-element Array{Int64,1}:
0
1
1
julia> for i in axes(b, 1)
b[i] > 0 && (a[i] = Int64[0,0,5])
end
julia> a
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[0, 0, 5]
[0, 0, 5]
julia> a[2][1] = 100
100
julia> a
3-element Array{Array{Int64,1},1}:
[1, 0, 0]
[100, 0, 5]
[0, 0, 5]
and you can see that each entry of a is a distinct object.
Logical indexing only selects those elements for which the condition is true. In your case of a[b.>0], that selects two elements:
julia> a[b.>0]
2-element Array{Int64,1}:
2
3
You are attempting to assign three elements into those two locations:
julia> a[b.>0] .= [10,20,30]
ERROR: DimensionMismatch("array could not be broadcast to match destination")
What you can do is also subset the values array you're assigning with the same conditional logic to pick which two elements should be assigned:
julia> a[b.>0] .= [10,20,30][b.>0]
2-element view(::Array{Int64,1}, [2, 3]) with eltype Int64:
20
30
julia> a
3-element Array{Int64,1}:
1
20
30
The syntax a[b.>0] .= [Int64[0,0,5]] will only work if a is an Any array, and it means something completely different. It broadcasts the values array itself into all the selected locations — that is, it puts the whole array as repeated elements in a!
julia> a = Any[1,2,3]
3-element Array{Any,1}:
1
2
3
julia> a[b.>0] .= [Int64[0,0,5]]
2-element view(::Array{Any,1}, [2, 3]) with eltype Any:
[0, 0, 5]
[0, 0, 5]
julia> a
3-element Array{Any,1}:
1
[0, 0, 5]
[0, 0, 5]

How to initialise reduce and use accumulator in Julia

It works without initial value:
reduce(+, [2 3 4])
Tried multiple ways to provide initial value - nothing works
reduce(+, [2 3 4], 1)
reduce(+, 1, [2 3 4])
Also seems like reduce could be used only with 2 argument operator. What function should be used to reduce collection with custom functions that accept current value and accumulator? Something like code below?
reduce((accumulator, value) -> push!(accumulator, value^2), [1, 2, 3], [])
# => [1, 4, 9]
This example could be implemented as map(x -> x^2, [1, 2, 3]) but I would like to know how to implement it as reduce with accumulator.
julia version 1.1.1
The init argument to reduce is a keyword argument:
julia> reduce(+, [2 3 4], init = 1)
10
julia> reduce((accumulator, value) -> push!(accumulator, value^2), [1, 2, 3], init = [])
3-element Array{Any,1}:
1
4
9

Vectors of length N with elements from another vector (with repetition)

Is there any easy way to generate an array of permutations of length N, drawn from k values? Example:
N = 2
k = [[0 0], [0 1], [1 0], [1 1]]
Permutations = [
[[0 0], [0 0]],
[[0 0], [0 1]],
[[0 0], [1 0]],
[[0 0], [1 1]],
[[0 1], [0 0]],
[[0 1], [0 1]],
[[0 1], [1 0]],
[[0 1], [1 1]],
...
]
An important note here: If possible, I'd like the result to be arrays all the way down (the product function in the Iterators package generates tuples)
If it helps, the Haskell equivalent would be: replicateM 2 [[0, 0], [0, 1], [1, 0], [1, 1]]
Just in case there's a more idiomatic way to achieve what I'm trying to do, here's the function I'm writing:
function generate_states(length)
# "tuples" contains what I want, but it needs a lot of transformation to
# be usable later
tuples = [collect(t) for t in
product([product(0:1, 0:1) for _ in 1:length]...)]
states = collect(distinct(imap(x -> kron([[i...] for i in x]...), tuples)))
return states
end
Which works, and does what I want, but ideally I'd like it to look something like this:
function generate_states(length)
arrays = replicateM(3, Array[[0 0], [0 1], [1 0], [1 1]])
states = collect(distinct(imap(x -> kron(x...), arrays)))
return states
end
UPDATE / FIX
The question actually wants to generate all the sequences of length N of elements from k.
This could be achieved using:
using Iterators # install package with `Pkg.add("Iterators")`
N = 2
k = Array[[0 0], [0 1], [1 0], [1 1]]
res = [Array[e...] for e in product(fill(k,N)...)]
OLDER INTERPRETATION - permutations of objects
collect(combinations(['a','b','c','d'],2)) generates the right collection disregarding the elements being permuted.
The specific elements in your code [0 0] are row vectors (i.e. 1x2 matrices). This is more awkward than column vectors in Julia. The example with column vectors is:
julia> combinations(Array[[0,0],[0,1],[1,0],[1,1]],2) |> collect
6-element Array{Array{Array{Int64,1},1},1}:
[[0,0],[0,1]]
[[0,0],[1,0]]
[[0,0],[1,1]]
[[0,1],[1,0]]
[[0,1],[1,1]]
[[1,0],[1,1]]
Note the explicit typing of [] to prevent flattening of internal elements by vcat. With row vectors, as in the OP:
combinations(Array[[0 0],[0 1],[1 0],[1 1]],2) |> collect
(standard output is messy)
There's a simple solution with tuples as follows:
K = [(0,0), (0,1), (1,0), (1,1)]
vec( [(i,j) for i in K, j in K] )
If you really need arrays (why do you need this?) you can do
K2 = [ [a...] for a in K ]
[ a for a in vec( [(i,j) for i in K2, j in K2] ) ]
If you need arrays of arrays then that is also possible, but even more messy. So the question is, can you really not get use tuples of tuples?

Recursion and basecase in prolog

I have a function which I can not get to run correctly and I cant figure out why. I think it may have to do with the base case.
This is what I have:
recursion(Start, [Tail|Tails], [Alpha|Alphas], Beta, [X|Xs]):-
third(Start, Alpha, S),
second(S,Beta,Tail,X),
recursion(Start, Tails, Alphas, Beta,Xs).
recursion([],[],[],_,[]).
I know that the second function works correctly but when I run this:
recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, X).
I get:
T Call: (6) recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, _G3980)
T Fail: (6) recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, _G3980)
false.
My other predicates can be found:
second(A,B,_,1) :- A > B.
second(A,B,C,C) :- A == B.
second(A,B,_,-1) :- A < B.
third([A|As], [B|Bs], X) :-
third(As, Bs, Z),
X is Z + A* B.
third([],[],0).
UPDATE:
Start and Tail will both be the exact same list entered into the predicate. Thats why in the example they are both [1,2]. When I change my base case to recursion(_,[],[],_,[]). I get:
98 ?- recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, X).
T Call: (6) recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, _G1632)
T Redo: (6) recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, _G1632)
T Fail: (6) recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, _G1632)
false.
Any ideas?
Your base case is not getting accessed because Start is passed to recursion unchanged. Therefore, it will never unify with the empty list, meaning that only the first clause of recursion will be used.
It does not look like Start is being used in your function, so you might either ignore it, like that
recursion(_, [],[],_,[]).
or remove it altogether, like this:
recursion([Tail|Tails], [Alpha|Alphas], Beta, [X|Xs]):-
second(5,Beta,Tail,X),
recursion(Tails, Alphas, Beta,Xs).
recursion([],[],_,[]).

Resources