How to use map to multiply two vectors

Given these two vectors,

x = [1,2,3]; y=[4,5,6]

I understand why this is true:

x * y' == *(x, y')

But I do not understand why this is true or, better, why * does not multiply the two vectors the same way. How can I use map to multiply the two vectors?

C0 = map(*, x, y')

C1 = map((a,b) -> a * b, x, y')

C2 = map((a,b) -> a * b, x, y)

C0 == C1 == C2

map is element-wise, x * y' is not element-wise, it’s a column vector * a row vector, so an outer product

1 Like

This is where you use broadcasting instead of map. It broadcasts across singleton dimensions, and in this particular case, it is trivial to express it as

x .* y'

There’s not all that much point to change from x * y' to x .* y' in and of itself. But you can fuse it with other operations, or do it in-place, like this

A .= x .* y'
1 Like

x .* y' == map.(*, x, y')

1 Like

This gives an error: A is not defined.

So the answer to my question is:

map.(*, x, y')

It’s for when you have predefined an output array, which I called A as an example.

I think this was probably intended as a joke. Combining map and broadcast like that is pointless (but fun).

Just use broadcast.

1 Like

OK. Just like this:

A = zeros(Int, (3, 3))

A .= x .* y'

that’s not helpful for OP I think.

By definition, map.() is doing map for individual element, if you’re writing this you might as well do

x .* y'

julia> x .* y' == x * y'
true

but THIS IS AN COINCIDENCE,

julia> x' .* y == x' * y
false

like, the point shouldn’t be literally use “map” somewhere in the code, the point is map is doing element operation and the * inside x * y' is conceptually not an element-wise operation

1 Like

x' * y == mapreduce(*, +, x, y)

I still don’t understand why you are insisting on showing simple linear algebra concepts like “dot product” and “outer product” can be expressed using something containing the word “map” – how is this helpful for a beginner like OP?

I was only trying to find a Julia function similar to the R outer function, where outer(x, y, FUN = "*") == x %*% t(y). FUN is a vectorized function like + or +. That is why I was trying to use map in Julia.

And this mapping horror:

using LinearAlgebra
cross(x,y) == map(.*, circshift(x,2), circshift(y,1)) - map(.*, circshift(x,1), circshift(y,2))

In Julia you don’t use any special function for this, you just broadcast whatever operator you want, like x .* y', x .+ y', x .< y', x .% y', etc etc etc.

1 Like

OK. But how could you do in Julia something like this in R:

f <- outer(x, y , function(x, y) cos(y) / (1 + x^2))

cos.(y') ./ (1 .+ x.^2), or more simply @. cos(y') / (1+x^2)

2 Likes

I got a different result using R:

> f
            [,1]       [,2]       [,3]
[1,] -0.32682181 0.14183109 0.48008514
[2,] -0.13072872 0.05673244 0.19203406
[3,] -0.06536436 0.02836622 0.09601703

and in Julia

julia> @. cos(y') / (1+x^2)
3Ă—1 Matrix{Float64}:
 -0.32682181043180597
  0.05673243709264525
  0.0960170286650366

Up to rounding error, that’s what I get in Julia also.

julia> x = [1,2,3]; y=[4,5,6];

julia> @. cos(y') / (1+x^2)
3Ă—3 Matrix{Float64}:
 -0.326822   0.141831   0.480085
 -0.130729   0.0567324  0.192034
 -0.0653644  0.0283662  0.096017
2 Likes