New user self-registration is currently disabled. Please email eigen-core-team @ lists.tuxfamily.org if you need an account.
Bug 1193 - extend lpNorm with 0 and -infinity
extend lpNorm with 0 and -infinity
Status: DECISIONNEEDED
Product: Eigen
Classification: Unclassified
Component: Core - general
unspecified
All All
: Normal Feature Request
Assigned To: Nobody
: JuniorJob
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2016-04-08 08:50 UTC by MartinS
Modified: 2016-07-25 13:34 UTC (History)
4 users (show)



Attachments

Description MartinS 2016-04-08 08:50:13 UTC
Currently, v.lpNorm<Infinity>() is implemented as v.cwiseAbs().maxCoeff(), which fails for the corner case of an empty vector. In many occasions, a result of 0 would be more convenient (and also consistent with other p-norms). Also, both Matlab's and Octave's norm([], inf) return 0 (although via interpreting [] as a matrix instead of a vector and applying the matrix inf-norm definition).

Of course, one could always check for v.size() > 0 before invoking v.lpNorm<Infinity>(), but this looks inconvenient, especially in templated code where the norm type is a parameter.
Moving the check to src/Core/Dot.h, lpNorm_selector<..., Infinity> (line 233 in current dev branch) seems more appropriate.

Btw. Are there any plans of adding more specializations to lpNorm, e.g.
- v.lpNorm<0> ==> v.array().count() 
- v.lpNorm<NegativeInfinity> ==> v.cwiseAbs().minCoeff()
(with a new constant Eigen::NegativeInfinity)
Comment 1 Gael Guennebaud 2016-06-02 13:34:58 UTC
Fixed: https://bitbucket.org/eigen/eigen/commits/677c9f157781/

Regarding L_0, v.array().count() does not define a proper norm, and L_0 refers to another definition for mathematicians, i.e.: (v.abs()/(1+v.abs())).sum()/2^n

Regarding minus infinity, are there any use cases?
Comment 2 Christoph Hertzberg 2016-06-06 13:45:22 UTC
Using \ell_0 as "counting norm" is not completely uncommon:
https://en.wikipedia.org/wiki/Lp_space#When_p_.3D_0

But, I guess using v.array().count() would definitely be less confusing here.
The same goes for v.cwiseAbs().minCoeff() instead of lpNorm<NegativeInfinity>();

We could also consider providing a  v.lpNorm(const RealScalar& p)  function (allowing non-integer p), which for for p<1 returns the corresponding pseudo norm (however, for p-->0 the natural limit for anything with more than one non-zero would be infinity instead of .array().count() -- and for floating point values checking != 0.0 actually is often meaningless ...)
Comment 3 Gael Guennebaud 2016-06-06 15:03:45 UTC
yes, I perfectly agree that using L_0 as v.array().count() is extremely common! I just wanted to point out that there do exist a risk of ambiguity.

Ok for v.lpNorm(const RealScalar& p).
Comment 4 MartinS 2016-06-07 10:16:57 UTC
Thanks for the fix!

Regarding the 0-case: After checking the Wikipedia article, I also agree that v.array().count() is less ambiguous and should be preferred. 

The variant with a runtime norm type is a good idea, though. For performance reasons, I would also propose an integer overload that behaves exactly as the templated version for the special argument values 1, 2 and Eigen::Infinity.

Regarding minus infinity: I had no particular use case in mind. It was just a consideration for bringing the API on par with Matlab/Octave.

Note You need to log in before you can comment on or make changes to this bug.