Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add new vecnorm(x, p), generalizing and replacing normfro #6057

Merged
merged 1 commit into from
Mar 5, 2014

Conversation

stevengj
Copy link
Member

@stevengj stevengj commented Mar 5, 2014

As discussed on the mailing list, this adds a new vecnorm(x,p) function (generalizing and replacing normfro) which computes a p-norm of any iterable container as if it were a vector.

Along the way, I also made a few other improvements, e.g. the generic-p case no longer allocates temporary arrays, accumulation is done in double precision for Float16 or Float32 arrays (but the result is still returned as Float16 or Float32), and cheapnorm in quadgk is eliminated in favor of vecnorm.

Also fixes #6056 (makes norm type-stable).

cc: @toivoh, @StefanKarpinski

@stevengj
Copy link
Member Author

stevengj commented Mar 5, 2014

Also, note that I changed the various norm functions to accept only p::Real, rather than p::Number. Non-Real values for p made no sense to me whatsoever.

@@ -400,6 +400,7 @@ eval(Sys, :(@deprecate shlib_list dllist))
IntSet(xs::Integer...) = (s=IntSet(); for a in xs; push!(s,a); end; s)
Set{T<:Number}(xs::T...) = Set{T}(xs)

@deprecate normfro(A) vecnorm(A)
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normfro should also be removed from exports.jl.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't it have to be in exports because it still exists, albeit in deprecated form?

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the @deprecate macro automatically exports it for you (there's no point in having a private deprecation, after all).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay. Will fix.

@JeffBezanson
Copy link
Sponsor Member

Really nice.

@pao
Copy link
Member

pao commented Mar 5, 2014

Can we get a NEWS.md snippet for the behavior change to norm() with a row vector as well?

end
return a
return float(minabs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not necessary to do the conversion here. It should be done in vecnorm. This function is type stable without the conversion.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just as easy to do the conversion here, and things are a bit more uniform if all the vecnormX functions return the same type.

@andreasnoack
Copy link
Member

Actually, I considered the type instability of norm a feature, because I like that the 1- and inf-norms return integers for integer input, but I recognise the type inference problem. I've just realised that the old norm2(AbstractVector) suffered from that. However, I don't think it is necessary do the conversion before vecnorm.

@pao I did that yesterday.

@toivoh
Copy link
Contributor

toivoh commented Mar 5, 2014

It can definitely be nice to get the 1-norm or inf-form of an integer array as an integer, but I believe that the type instability might be a real performance issue. Maybe we should add norm1, norminf, vecnorm1, and vecnorminf, for these cases? Though it feels a bit ugly that we should need to add four functions for it...

@stevengj
Copy link
Member Author

stevengj commented Mar 5, 2014

I really don't see the practical utility of integer-valued norm functions. Vectors of integers don't form a Banach space... where would an integer-valued norm be useful?

@StefanKarpinski
Copy link
Sponsor Member

I really don't see the practical utility of integer-valued norm functions. Vectors of integers don't form a Banach space... where would an integer-valued norm be useful?

Full agree with this. Returning integer norms doesn't make any sense to me.

@StefanKarpinski
Copy link
Sponsor Member

Of all people, I think @stevengj is the last one we have to worry about not updating the docs.

@stevengj
Copy link
Member Author

stevengj commented Mar 5, 2014

(I will add a NEWS item, but I usually add a NEWS item after the patch is merged.)

@andreasnoack
Copy link
Member

Do vectors of floats form a Banach space? What has completeness to do with this? Are integers less real than floats? And what about the minus infinity norm?

@stevengj
Copy link
Member Author

stevengj commented Mar 5, 2014

Vectors of floats are a reasonable approximation for vectors of reals, and are well-accepted as such. Vectors of integers are not. (Yes, integers are still subsets of the reals, but if you view them as a mere subset rather than as a sub-space then there is no need for the return type to be an Integer.) Of course, this doesn't mean their "norm" is not useful, but it eliminates all the usual algebraic justifications for a norm function — you need to find some other need for it in order to justify its existence.

Yes, we compute several things that are not norms. I was particularly skeptical of the utility of the p < 0 norms. But at least they are continuous functions for a certain subset of the reals, and don't require any extra code to compute (except for p=-Inf) so I suppose we might as well support them.

@pao
Copy link
Member

pao commented Mar 5, 2014

Of all people, I think @stevengj is the last one we have to worry about not updating the docs.

The change to document isn't a part of this patch (it was already changed), so it seemed worth noting that as a separate item, particularly because it's a non-deprecable (deprecatable?) change.

@lindahua
Copy link
Contributor

lindahua commented Mar 5, 2014

It is true that from a math standpoint that norms only make sense in Banach space.

However, allowing vectors of integers as input would be quite handy especially in interactive sessions. For example, I think it would be reasonable to expect the following to work:

vecnorm([1,2,3])

This may be interpreted as treating [1,2,3] as a real vector and computing the vector norm. I don't see this would violate the math correctness much.

@StefanKarpinski
Copy link
Sponsor Member

That's not the argument – the question is whether the 1-norm of an integer vector should be integral or floating point. And @stevengj and I are arguing that it doesn't make much sense to get an integral norm value even though in the case of the 1-norm the result happens to always be an integer.

@lindahua
Copy link
Contributor

lindahua commented Mar 5, 2014

Ok. Then I agree with using floating point value for the norm.

@toivoh
Copy link
Contributor

toivoh commented Mar 5, 2014

I actually do think that 1- and inf-norms make sense for integer matrices as well. Integer matrices are closed under matrix addition and multiplication, these vector norms give integer values on integer vectors, as do the induced norms on integer matrices, which in turn give exact bounds on the maximal amplification that an integer matrix will cause in the respective norms. Coincidence or not, there is clearly some mathematical structure here.

That said, integer 1- and inf-norms are probably a niche enough application, and it's easy to roll your own.

@stevengj
Copy link
Member Author

stevengj commented Mar 5, 2014

@toivoh, much of the concept of "linear algebra" goes out the window for integer matrices and vectors, because integer vectors are not a vector space (over the integers) because integers do not form a field (with the usual + and *). Yes, you can still define certain operations, but the practical utility of those operations is greatly limited compared to the situation where you have a vector space (and especially a complete normed vector space, i.e. a Banach space).

The question is, are there any real-world applications of integer-valued L1 norms in which returning a Float64 norm value is not sufficient? Moreover, do they outweigh the performance advantages of having norm(x,p) and vecnorm(x,p) be type-stable? So far, the answer seems to be a resounding no.

@toivoh
Copy link
Contributor

toivoh commented Mar 5, 2014

Oh, I definitely agree that norm and vecnorm should be type-stable. The
only question is whether we should expose specialized 1- and inf-norms as
well. I personally think that that would be nice, but I'm fine with not
doing it.

@stevengj
Copy link
Member Author

stevengj commented Mar 5, 2014

The question of having different norm functions with various names was discussed back in #1875.

@StefanKarpinski
Copy link
Sponsor Member

In the context of wanting an integer answer for integer inputs, while what you're computing may happen to be the same as the 1-norm or the inf-norm, in such cases, I'd say you are doing abs-sum or abs-max reduction, rather than taking a norm. Exposing those computations as norms is weird.

@toivoh
Copy link
Contributor

toivoh commented Mar 5, 2014

Yes, but that was before the type stability issue was brought up. Anyway,
please carry on.

@andreasnoack
Copy link
Member

@stevengj If you insist that the input type represents the field of the vector space then think of the Julia type hate most: Rational{Int}.

However, my math arguments won't make the type inference problem go away.

@stevengj
Copy link
Member Author

stevengj commented Mar 5, 2014

@andreasnoackjensen, I don't want to restrict the input type, I want to make the output type floating-point. We should certainly accept rational (and integer) vectors as input, but it is insane for the L1 norm (for instance) to try to return a rational output (= near-certain overflow for fixed-precision types, and exponential complexity for Rational{BigInt}).

Even when we can practically compute a rational or integer result from a norm function (e.g. for the Linf norm of a rational vector or the L1 norm of an integer vector), I don't think that we should, because the additional code required is simply not matched by any practical benefit. So far, not a single practical use of an integer- or rational-valued norm (vs. float-valued) has been raised.

(PS. While vectors over the rationals are indeed a vector space, the are not a Banach space because they are not complete.)

@StefanKarpinski
Copy link
Sponsor Member

Be it resolved that norm returns an appropriate floating-point type.

@stevengj
Copy link
Member Author

stevengj commented Mar 5, 2014

So is the patch okay to merge?

StefanKarpinski added a commit that referenced this pull request Mar 5, 2014
add new vecnorm(x, p), generalizing and replacing normfro
@StefanKarpinski StefanKarpinski merged commit a0ea09a into JuliaLang:master Mar 5, 2014
@andreasnoack
Copy link
Member

I think it is unfortunate to promote when there is no reason to do it. For norm(x,p) there is a type inference problem but not for vecnormInf or vecnorm1. No mathematical sound argument has been raised for promoting to floating point. What in the definition of a norm excludes integer valued output? You pretend that integers are not real numbers and I simply don't agree in that. I don't think that because 0.5+0.5 is a floating point 1+1 should be a floating point.

A cool thing about Julia is that you can write very generic code such that you can define a new Number type and compute with it. For the generic LU, the number type only has to be stable under division and for the generic QR it has to stable under normalisation with the Euclidian norm. Then someone can define a new type and just use the LU factorisation on that or another new type and do QR and eigenvalue calculations. I can't see that it makes the code more complicated, (maybe not assuming commutativity makes it slightly more complicated). The only complicated thing is to make the right promotion.

It would have costed you ten seconds of work to acknowledge that point and move the promotion to floating point from vecnormInf and vecnorm1 to vecnorm. Instead we have wasted out time on mentioning such things as Banach spaces, which complete irrelevant to this issue.

@stevengj
Copy link
Member Author

stevengj commented Mar 6, 2014

You should never call them elsewhere because they don't even handle the isempty iterable case (since this way the isempty check occurs only once rather than in 5 places). Putting the float call in vecnormInf saves calling it (or similar complications) not just in vecnorm but in vecnorm2 and vecnormp. Given that, you might as well put float in vecnorm1 too for uniformity's sake, not to mention that the sum is done in floating point to prevent overflows.

I don't see the point in duplicating code, even if it is a few simple calls, and risking overflows to return a result no one wants from functions no one will call.

@alanedelman
Copy link
Contributor

At the risk of jumping in without reading the whole thread --- I still hate the name
vecnorm for normfro -- because it forgets that normfro is indeed a matrix norm

i'm okay with both existing, and no depracating

my two cents

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

norm is not type-stable
8 participants