Hi Werner,
Thanks for the reply. The context for this is that I was trying to design a neural networking library. I made the assumption that it made sense to accept vectors, apply matrix operations to them, and return vectors. My initial experiments with matrices and vectors seemed to suggest this would work. However, it then took several days experimenting and debugging to uncover the precise semantics of matrix-vector interactions. These semantics were not obvious to me from my initial experiments. Furthermore, I ultimately discovered that, as best I could tell, the operations I wanted to perform were not possible at all with the standard api, and that I needed to rewrite the whole critical path to use only matrices. Since vectors are not consistently 1xn or nx1, I could not simply change my vector inputs to matrices, but had to rewrite the entire critical path to get the orientations right. Overall, this seemed to suggest to me that either vectors and matrices should be made fully compatible, or entirely incompatible, but should not work sometimes and not others. Based on the difficulties you and others have pointed out, I think you are right that it would be difficult to unify the protocols, and that matrices and vectors should just not interoperate at all. Serge seemed to suggest that that was a basic assumption of the library.
See my specific comments inline below.
On Saturday, May 20, 2017 at 6:33:29 PM UTC-4, werner kassens wrote:
Hi Evan,
reducing 1-dimensional vectors to scalars is not such a good idea:
1. the whole vector protocol consists also of the Array protocol, the ArrayedCollection, the SequenceableCollection and the Collection protocol.
2. a 1-dimensional vector _is_ something different than a scalar! eg a whole lot of methods take an Array as argument, even if it has only one dimension, but usually they wouldnt work with a scalar. hence you can't "expect 1-dimensional vectors to act like scalars".
Since I'm not sure what a "1-dimensional vector" means mathematically, I'm not sure how it should behave, even though we can clearly define the concept in PolyMath. Fortunately, I don't think it will come up as long as matrices and vectors inhabit different worlds.
re: #(2) asPMVector * (PMMatrix rows: #((1 2) (3 4))). "a PMVector(2 4)"
yes, this is in a way a problem and the problem is here:
#(2 3) asPMVector * #(1) asPMVector."2"
there exists the occasional warning here & there, that for speed reasons no size-check is made - well, <g> probably more there than here -, but unfortunately this warning does at the moment not exist in PMVector>>productWithVector: . if this would have a size-check, this result would not happen. but it would slow down the calculations a tiny bit, since productWithVector: is called very very often. i would prefer if these things would not be made slower than necessary. one just has to pay attention and not produce nonsense code. so that your (and my) example also produces an error you would have to change PMVector>>productWithVector: to produce an SizeMismatch error or so. ok, i think this is unnecessary, but if i'm the only one who wants these things to be fast, then just change it (i can also use earlier versions for real-world-calculations if things are getting too slow for me because of all kinds of error-checks one can think of).
That is a good point. We can probably make the default math safe and add clearly marked unsafe operations for speed. I aspire every day to not to write buggy, nonsense code but alas, that day has not yet come. Would that work for everyone? You shouldn't need to use an old library to get performant math, but I just had all my tests passing for most of my development even though I was comparing matrices of different dimensions just because it only checked one row!
"n-dimensional vectors...cannot be used as either a 1xn or an nx1 matrix in code that expects one or the other"
<g> you can 'practically' specify that by using "( )" around a matrix & vector multiplication with the correct sequence (or simply by using a matrix instead). where else would you really need to make that distinction for a vector? at the moment, i have to admit, i dont really see the problem.
werner
Can you? I could not find a way to use any sort of order or grouping that resulted in the calculation I wanted.
a := PMMatrix rows: #((1 2)).
b := PMMatrix rows: #((1) (2)).
c := #(1 2) asPMVector.
Using a and b, I can get a 2x2 matrix:
b * a. "a PMVector(1 2) a PMVector(2 4)"
How can I perform that multiplication with c and either a or b? This was the show stopper that finally made me stop trying to get vectors to work and rewrite everything with matrices:
a * c "a PMVector(5)"
c * a "Error"
c * b. "a PMVector(5)"
b * c. "Error"
Hope that helps clarify things,
Cheers,
Evan
Mathematically, we might expect 1-dimensional vectors to act like scalars and nx1-dimensional matrices to act like vectors. There are some important places where current implementations seem to violate these expectations:
1-dimensional vectors are not scalars with respect to vectors:
2 * #(1 2 3) asPMVector. "a PMVector(2 4 6)"
#(2) asPMVector * #(1 2 3) asPMVector. "Error"
1-dimensional vectors are not scalars with respect to matrices, and in fact have undefined behavior:
2 * (PMMatrix rows: #((1 2) (3 4))). "a PMVector(2 4) a PMVector(6 8)"
#(2) asPMVector * (PMMatrix rows: #((1 2) (3 4))). "a PMVector(2 4)"
n-dimensional vectors are row vectors when right-multiplied by an nx1 matrix, but column vectors when left multiplied by a matrix 1xn, meaning they cannot be used as either a 1xn or an nx1 matrix in code that expects one or the other: the dimensions will be unpredictable.
#(1 2) asPMVector * (PMMatrix rows: #((1) (2))). "a PMVector(5)"
(PMMatrix rows: #((1 2))) * #(1 2) asPMVector. "a PMVector(5)"
1x1 matrices are not scalars with respect to vectors:
(PMMatrix rows: #((2))) * #(1 2) asPMVector. "Error"
1xn * nx1 matrix multiplication produces a matrix, not a scalar, which behaves differently than a scalar, as per above:
(PMMatrix rows: #((1 2))) * (PMMatrix rows: #((1) (2))) "a PMVector(5) <-- actually a 1x1 matrix"
As long as one works only with scalars and vectors OR scalars and matrices, things seem fine. It seems like maybe either matrix-vector operations should throw errors, or vectors should behave consistently as an nx1 matrix during matrix math. It may also make sense to make the 1-dimensional vectors and matrices either just convert to scalar Numbers, or make them polymorphic with #= etc, but I'm not sure.
--
You received this message because you are subscribed to the Google Groups "SciSmalltalk" group.