commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Gilles <gil...@harfang.homelinux.org>
Subject Re: [math] Should this throw a NO_DATA exception?
Date Sat, 09 Jan 2016 12:21:29 GMT
Hello.

On Sat, 9 Jan 2016 00:27:37 -0600, Ole Ersoy wrote:
> Hi Gilles,
>
> On 01/08/2016 07:37 PM, Gilles wrote:
>> Hi Ole.
>>
>> Maybe I don't understand the point of the question but I'm
>> not sure that collecting here answers to implementation-level
>> questions is going to lead us anywhere.
> Well it could lead to an improved implementation :).

But we should know the target of the improvement.
I mean, is it a drop-in replacement of the current "RealVector"?

If so, how can it happen before we agree that Java 8 JDK can be
used in the next major release of CM?

If it's a redesign, maybe we should define a "wish list" of what
properties should belong to which concept.
E.g. for a "matrix" it might be useful to be mutable (as per
previous discussions on the subject), but for a (geometrical)
vector it might be interesting to not be (as in the case for
"Vector3D" in the "geometry" package).

The "matrix" concept probably requires a more advanced interface
in order to allow efficient implementations of basic operations
like multiplication...

>>
>> There is a issue on the bug-tracking system that started to
>> collect many of the various problems (specific and general)
>> of data containers ("RealVector", "RealMatrix", etc.) of the
>> "o.a.c.m.linear" package.
>>
>>
>> Perhaps it should more useful, for future reference, to list
>> everything in one place.
> Sure - I think in this case though we can knock it out fast.
> Sometimes when we list everything in one place people look at it, get
> a headache, and start drinking :).  To me it seems like a vector that
> is empty (no elements) is different from having a vector with 1 or
> more 0d entries.  In the latter case, according to the formula, the
> norm is zero, but in the first case, is it?

To be on the safe side, it should be an error, but I've just had
to let this kind of condition pass (cf. MATH-1300 and related on
the implemenation of "nextBytes(byte[],int,int)" feature).

>
>>
>> On Fri, 8 Jan 2016 18:41:27 -0600, Ole Ersoy wrote:
>>> public double getLInfNorm() {
>>>         double norm = 0;
>>>         Iterator<Entry> it = iterator();
>>>         while (it.hasNext()) {
>>>             final Entry e = it.next();
>>>             norm = FastMath.max(norm, FastMath.abs(e.getValue()));
>>>         }
>>>         return norm;
>>>     }
>>
>> The main problem with the above is that it assumes that the elements
>> of a "RealVector" are Cartesian coordinates.
>> There is no provision that it must be the case, and assuming it is
>> then in contradiction with other methods like "append".
>
> While experimenting with the design of the current implementation I
> ended up throwing the exception.  I think it's the right thing to do.
> The net effect is that if someone creates a new ArrayVector(new
> double[]{}), then the exception is thrown, so if they don't want it
> thrown then they should new ArrayVector(new double[]{0}).   More
> explanations of this design below ...

I don't know at this point (not knowing the intended usage).
[I think this is low-level discussion that is not impacting on the
design but would fixe an API at a too early stage.]

>>
>> At first (and second and third) sight, I think that these container
>> classes should be abandoned and replaced by specific ones.
>> For example:
>> * Single "matrix" abstract type or interface for computations in
>>   the "linear" package (rather than "vector" and "matrix" types)
>> * Perhaps a "DoubleArray" (for such things as "append", etc.).
>>   And by the way, there already exists "ResizableDoubleArray" which
>>   could be a start.
>> * Geometrical vectors (that can perhaps support various coordinate
>>   systems)
>> * ...
>
> I think we are thinking along the same lines here.  So far I have the
> following:
> A Vector interface with only these methods:
> - getDimension()
> - getEntry()
> - setEntry()

And what is the concept that is being represented by this interface?

I think that is necessary to list use-cases so that we don't again
come up with a design that may prove not specific enough to satisfy
some requirements of the purported audience.

> An ArrayVector implements Vector implementation where the one and
> only constructor takes a double[] array argument.  The vector length
> cannot be mutated.  If someone wants to do that they have to create a
> new one.

Assuming we explore the 3 concepts I had listed above
* it cannot be "matrix" (since I supposed that a row or column matrix
   could be of type "matrix" not "vector")
* it cannot be an appendable sequence, since the size is fixed.
* it cannot be a geometrical vector since "getEntry(int)" and
   "setEntry(int, double)" are too low level to ensure consistency
   under transformations (since we cannot assume that the entries
   would always be Cartesian coordinates).

>
> A VectorFunctionFactory class containing methods that return Function
> and BiFunction instances that can be used to perform vector mapping
> and reduction.  For example:
>
>     /**
>      * Returns a {@link Function} that produces the lInfNorm of the 
> vector
>      * {@code v} .
>      *
>      * Example {@code lInfNorm().apply(v);}
>      * @throws MathException
>      *             Of type {@code NO_DATA} if {@code 
> v1.getDimension()} == 0.
>      */
>     public static Function<Vector, Double> lInfNorm() {
>         return lInfNorm(false);
>     };
>
>     /**
>      * Returns a {@link Function} that produces the lInfNormNorm of
> the vector
>      * {@code v} .
>      *
>      * Example {@code lInfNorm(true).apply(v);}
>      *
>      * @param parallel
>      *            Whether to perform the operation in parallel.
>      * @throws MathException
>      *             Of type {@code NO_DATA} if {@code 
> v.getDimension()}  == 0.
>      *
>      */
>     public static Function<Vector, Double> lInfNorm(boolean parallel) 
> {
>         return (v) -> {
> LinearExceptionFactory.checkNoVectorData(v.getDimension());
>             IntStream stream = range(0, v.getDimension());
>             stream = parallel ? stream.parallel() : stream;
>             return stream.mapToDouble(i ->
> Math.abs(v.getEntry(i))).max().getAsDouble();
>         };
>     }

This is a nice possibility, but without a purpose, it could seem that
you just move the "operations" from the container class to another one.
It's cleaner, certainly, but could it be that the factory will end up
with as many conceptually incompatible operations as the current 
design?

> So the design leaves more specialized structures like Sparce matrices
> to a different module.  I'm not sure if this is the best design, but
> so far I'm feeling pretty good about it.  WDYT?

So you were really working on the "matrix" design?
Did you look at what the requirements are for these structures
(e.g. for fast multiplication) and how they achieve it in other
packages (e.g. "ojalgo")?

If it's not about "matrix" but about blocks of (possibly 
multi-dimensional)
data that can be "mapped" and "reduced", perhaps that the 
one-dimensional
version (which seems what your new "Vector" is) should just be a 
special
case of an interface for this kind of structure (?).
[It this latter case, the CM "MultidimensionalCounter" (in package 
"util")
might be something that can be reused (?).]

Best regards,
Gilles

>
> Cheers,
> Ole


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message