Norm, normalize

I just realized, that normalize only has methods for AbstractVectors.

julia> methods(normalize)
# 2 methods for generic function "normalize":
normalize(v::AbstractArray{T,1} where T) in Base.LinAlg at linalg/generic.jl:1294
normalize(v::AbstractArray{T,1} where T, p::Real) in Base.LinAlg at linalg/generic.jl:1294

And norm is only defined for vectors and matrices. Mathematically the p norm is reasonable for
arrays of any dimension, so to me it seems both of these should be defined for AbstractArray.

Is there a good reason for limiting these definitions?

2 Likes

It is usually not ambiguous how people would like to normalize a vector whereas I think that would be the case for matrices. We could choose a default but I’m not sure that there is as much a demand for that compared to how frequently people normalize vectors.

The norm function for matrices is the operator norm where the operator is applied with * on a Vector. We don’t define an operator for arrays of higher dimension so I think it is fine not to define a norm in that case. Notice that the elementwise norm function is called vecnorm and works for arrays of all dimensions and even iterators.

1 Like

It seems to me that the most consistent thing would be to define normalize!(x::T, p::Real) for all T accepted by norm(x::T, p::Real), and define vecnormalize! for the normalization by the Frobenius norm.

3 Likes

Would the proposed functionality produce the projection to the Lp unit ball? Or just divide each element by the norm? My impression is that these two concepts are equivalent for the L2 norm, but aren’t generally equivalent.

You are right, they differ. I prefer division. I often want to normalize the largest entry of an array to be one. This corresponds to division by Inf norm. Projection on the other hand is a quite useless operation in case of the Inf norm:
clamp.(arr, -1, 1)

Notice that you can simply do

scale!(A, inv(vecnorm(A, Inf)))

to achieve that which might be sufficient and not much longer than vecnormalize!(A, Inf). The normalize! function has the convenience of returning the norm and then it handles some corner cases.

Elementwise division by the norm seems the most predicable behavior to me, but maybe that’s just my background…

If it’s worth anything, it seems that Mathematica defines Normalize[expr, f] to do elementwise division by the norm calculated via f when expr is a matrix (the matrix example is under “Generalizations and Extensions”):

2 Likes