Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why plus operator is vectorized in Julia but not the division operator?

Tags:

julia

I am quite new with Julia, I am curious about the vectorized operations in Julia.

Example:

x = [2 3 4]
y = [3 4 5]

If I run the above with :

x + y

I get:

1×3 Array{Int64,2}:
 5  7  9

But If I do:

x/y

I get:

1×1 Array{Float64,2}:
 0.7600000000000002

Which I am unable to understand, after some research I found that x./y is the correct way of doing vectorized operation, but I wonder how come the plus sign working then.

Here are my questions:

What is the intuition behind this(Making plus symbol vectorized but not the division operator)?

Also what happens when I do x/y ? why .76000 is coming as an answer.

I hope this is not a duplicate, If it is Please let me know. I shall remove it. Thanks very much in advance. Please help.

like image 587
PKumar Avatar asked Dec 17 '22 12:12

PKumar


2 Answers

AFAICT + operator is not automatically broadcasted:

julia> 1 + [2, 3]
ERROR: MethodError: no method matching +(::Int64, ::Array{Int64,1})
For element-wise addition, use broadcasting with dot syntax: scalar .+ array

julia> [1 2] + [3, 4]
ERROR: DimensionMismatch("dimensions must match: a has dims (Base.OneTo(1), Base.OneTo(2)), b has dims (Base.OneTo(2),), mismatch at 1")

and you have to write respectively:

julia> 1 .+ [2, 3]
2-element Array{Int64,1}:
 3
 4

julia> [1 2] .+ [3, 4]
2×2 Array{Int64,2}:
 4  5
 5  6

What is important however, is that + is a valid operation (in a mathematical sense) for arrays of exactly the same dimension, that is why this works:

julia> [2 3 4] + [3 4 5]
1×3 Array{Int64,2}:
 5  7  9

note that this is not broadcasting but just linear algebra.

Now regarding x / y you can check that it is defined as:

help?>  x / y
  /(x, y)

  Right division operator: multiplication of x by the inverse of y on the right.

so you have:

julia> using LinearAlgebra

julia> x * pinv(y)
1×1 Array{Float64,2}:
 0.7600000000000005

(the actual implementation is a bit different - I am using a simplified approach here)

like image 113
Bogumił Kamiński Avatar answered Jun 17 '23 05:06

Bogumił Kamiński


+ is unambiguous in any array context. It operates element-wise and there is no other common interpretation. If the arrays are not a common size, then an error is thrown.

* is unambiguous in a matrix context (2-dimensional array). It refers to matrix multiplication. The length of the second dimension of the first input must match the length of the first dimension of the second input or else an error is thrown.

However, for general arrays, * is ambiguous. For example, if x and y are vectors of numbers (1-dimensional arrays), then what does x*y mean? Perhaps you want to perform the operation element-wise, or perhaps you wanted the inner product? Or a tensor product? For this reason * will throw an error if called with two vectors as the input. Note that .* is unambiguous, since by definition of broadcasting it just implies element-wise multiplication.

How does this relate to /? Note that / is the right division operator, that is, multiplication of x by the inverse or pseudo-inverse of y (where y is to the right of x). So the semantics of * apply here, with the additional constraint that y must be able to be inverted (or, at least, Moore-Penrose inverted). If these constraints are satisfied, then / is unambiguous and thus defined. If they are not satisfied then / will throw an error (at least, it should) :-)

This operation is definitely not element-wise, which is why ./ is distinct from / for the case of two vectors.

Now, bearing all this in mind, on to your example. First, note that you aren't actually defining vectors. A vector is defined [1,2]. But you are doing [1 2] which is actually a matrix. So the operation [1 2] / [3 4] is equivalent to [1 2] * pinv([3 4]). The pseudo-inverse is defined here, and since [1 2] is 1x2, and pinv([3 4]) is 2x1, the outcome will be a 1x2 x 2x1 array, that is, a 1x1 matrix, which is exactly what you got.

Note that [1,2] / [3,4] returns a 2x2 matrix. Again this makes sense, since [1,2] is implicitly 2x1, while pinv([3,4]) is 1x2, so the output will be 2x1 x 1x2 or rather, a 2x2 matrix.

like image 43
Colin T Bowers Avatar answered Jun 17 '23 06:06

Colin T Bowers