Intersection of two arrays by row - julia

I just switched to Julia from MATLAB and I am looking for a way to find the intersection of two arrays by row. For example, if C = [1 0;0 1], D = [-1 0;0 1] the output will be B, ind1, ind2 = [0 1], 2, 2.
A MATLAB counterpart would be: [B,ind1,ind2] = intersect(C,D,'rows')
How can I do this? Is there a built-in function in some module that would enable this operation?

Define:
function intersectML(ms::Array...)
t = map(x->Dict(x[2][i,:]=>(x[1],i) for i=1:size(x[2],1)),enumerate(ms))
u = intersect(map(keys,t)...)
return (u,map(x->[x[r][2] for r in u],t)...)
end
And then you have:
julia> C = [1 0;0 1]; D = [-1 0;0 1]
julia> intersectML(C,D)
(Array{Int64,1}[[0,1]],[2],[2])

Related

How can I slice the high-order multidimeonal array (or tensor) on the specific axis in Julia?

I am using Julia1.6
Here, X is a D-order multidimeonal array.
How can I slice from i to j on the d-th axis of X ?
Here is an exapmle in case of D=6 and d=4.
X = rand(3,5,6,6,5,6)
Y = X[:,:,:,i:j,:,:]
i and j are given values which are smaller than 6 in the above example.
You can use the built-in function selectdim
help?> selectdim
search: selectdim
selectdim(A, d::Integer, i)
Return a view of all the data of A where the index for dimension d equals i.
Equivalent to view(A,:,:,...,i,:,:,...) where i is in position d.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> A = [1 2 3 4; 5 6 7 8]
2×4 Matrix{Int64}:
1 2 3 4
5 6 7 8
julia> selectdim(A, 2, 3)
2-element view(::Matrix{Int64}, :, 3) with eltype Int64:
3
7
Which would be used something like:
julia> a = rand(10,10,10,10);
julia> selectedaxis = 5
5
julia> indices = 1:2
1:2
julia> selectdim(a,selectedaxis,indices)
Notice that in the documentation example, i is an integer, but you can use ranges of the form i:j as well.
If you need to just slice on a single axis, use the built in selectdim(A, dim, index), e.g., selectdim(X, 4, i:j).
If you need to slice more than one axis at a time, you can build the array that indexes the array by first creating an array of all Colons and then filling in the specified dimensions with the specified indices.
function selectdims(A, dims, indices)
indexer = repeat(Any[:], ndims(A))
for (dim, index) in zip(dims, indices)
indexer[dim] = index
end
return A[indexer...]
end
idx = ntuple( l -> l==d ? (i:j) : (:), D)
Y = X[idx...]

Evaluating a form field at a point on vectors in SageMath

I am having trouble matching up terminology in my textbook (Hubbard's Vector Calculus) against SageMath operators. I'd like to understand how to solve the following example problem with Sage:
Let phi = cos(x z) dx /\ dy be a 2-form on R^3. Evaluate it at the point (1, 2, pi) on the vectors [1, 0, 1], [2, 2, 3].
The expected answer is:
cos (1 * pi) * Matrix([1, 2], [0, 2]).det() = -2
So far I have pieced together the following:
E.<x,y,z> = EuclideanSpace(3, 'E')
f = E.diff_form(2, 'f')
f[1, 2] = cos(x * z)
point = E((1,2,pi), name='point')
anchor = f.at(point)
v1 = vector([1, 0, 1])
v2 = vector([2, 2, 3])
show(anchor(v1, v2))
which fails with the error:
TypeError: the argument no. 1 must be a module element
To construct a vector in E, I tried:
p1 = E(v1.list())
p2 = E(v2.list())
show(anchor(p1, p2))
but that fails with the same error. What's the right way to construct two vectors in E?
Almost there.
To evaluate the 2-form at point p,
use vectors based at p.
sage: T = E.tangent_space(point)
sage: T
Tangent space at Point point on the Euclidean space E
sage: pv1 = T(v1)
sage: pv2 = T(v2)
sage: pv1
Vector at Point point on the Euclidean space E
sage: pv2
Vector at Point point on the Euclidean space E
sage: anchor(pv1, pv2)
-2

In Julia, Transpose operator

I am trying to use a transpose operator over a vector in order to perform am element-wise addition.
For example, I want to add a column vector a = [a1;a2;a3] to a row vector b = [b1,b2] I should get matrix
M = a+b = [a1+b1, a1+b2; a2+b1, a2+b2; a3+b1, a3+b2].
In MATLAB it is equivalent (if both vectors are row vectors) M = a.'+b
I am trying to get the same in Julia but here is the problem, there is no .' operator in Julia starting from 1.0 version. There is the transpose operator which does not work in broadcasting mode. The adjoint operator is not Valid for me because I work with complex numbers.
a = Vector{ComplexF64}([1+3im,2])
b = Vector{ComplexF64}([0,0,0])
Z = zeros(ComplexF64,3,2)
G = zeros(ComplexF64,3,2)
#. Z = b + a' # Works but takes the complex conjugate
#. Z = b + transpose(a) # DOES NOT WORK!!!! The error is " DimensionMismatch("array could not be broadcast to match destination") "
Z = b .+ transpose(a) # Works but not efficient
#. Z = b + conj(a')
The third case Z = b .+ transpose(a) is not efficient because it makes 2 loops first one for addition b .+ transpose(a), than it runs the second loop one for the assignment of b .+ transpose(a) to Z. While the other 3 cases do it within one loop.
So which is the fastest way?
And why transpose doesn't within Broadcasting?
Thank you in advance
For Hermitian You can just type:
a' .+ b
Example
julia> a = ComplexF64.([1+3im,2])
2-element Array{Complex{Float64},1}:
1.0 + 3.0im
2.0 + 0.0im
julia> b = ComplexF64.([10,20,30])
3-element Array{Complex{Float64},1}:
10.0 + 0.0im
20.0 + 0.0im
30.0 + 0.0im
julia> a' .+ b
3×2 Array{Complex{Float64},2}:
11.0-3.0im 12.0+0.0im
21.0-3.0im 22.0+0.0im
31.0-3.0im 32.0+0.0im
If you want to have just transposition you could define your own unary operator (perhaps from the list of unused unary operators):
¬(a) = permutedims(a)
Now you could do
julia> ¬a
1×2 Matrix{ComplexF64}:
1.0+3.0im 2.0+0.0im

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?

Is there outer map function in Julia?

I am trying to construct all possible combinations of four vectors (parameters in a model) that would give me a big nx4 matrix and I could then run simulation on each set (row) of parameters. In R I would achieve this by using expand.grid in Mathematica style, I could use something like outer product with vcat and reduce the output using hcat.
Is there some function analog of expand.grid from R or outer map function?
Toy example:
A = [1 2]
B = [3 4]
some magic
output = [1 3, 1 4, 2 3, 2 4]
Using the Iterators package, it might look like this:
using Iterators
for p in product([1,2], [3,4])
println(p)
end
where you would replace println with your algorithm. You can also use collect if it's important to get the set of all combinations.
Not the exact notation you show, but a comprehension might be useful.
julia> a=[1, 2];
julia> b=[3, 4];
julia> [[i, j] for j in b, i in a]
2x2 Array{Any,2}:
[1,3] [2,3]
[1,4] [2,4]
julia> [[i, j] for j in b, i in a][:]
4-element Array{Any,1}:
[1,3]
[1,4]
[2,3]
[2,4]

Resources