Subject: Re: is/equal for lists/matrices -- design note
From: Stavros Macrakis
Date: Wed, 28 Jan 2004 14:19:03 -0500
Robert,
Thanks for your note.
I do agree that 1==[2] and
matrix([1,2,3],[4,5,6])==matrix([1,2],[3,4],[5,6]) and [1,2]==[1,2,3]
can't be true under any reasonable interpretation, and that compar-patch
doesn't handle those cases. But I decided it wasn't worth the trouble
to code cases like that in the absence of a coherent design which
resolves the truth/false/unknown status of 1==[1] and
[1,2]==matrix([1,2])==matrix([1],[2]).
I suppose we could simply decide pragmatically that 1 /= [1], that [1,2]
== matrix([1],[2]) but /= matrix([1,2]), even though [1,2] sometimes
functions as a row matrix. Or perhaps [] and matrix should never be ==?
If that is the answer, that is easy enough to program, and I can do it.
Maxima supports scalars, lists (interpreted as column vectors), and
matrices (2-dimensional). (To complicate matters, it sometimes allows
incompatible dimensions by transposing.) It also supports mathematical
operations on arbitrarily nested lists (listarith:true), but I'm not
aware they have any particular mathematical interpretation or
application, e.g. [1,[2,3]]+[[4,5],6] => [[5,6],[8,9]] and
[a,[b,c]].[[d,e],f] => [b*f+a*d,[c*f+a*e]].
Maxima also supports n-dimensional arrays for programming, but provides
no mathematical operations on them.
I agree with you entirely that some sort of unification would be nice.
In particular, arrays are definitely stuck on to Maxima in a completely
ad hoc way. It don't think it would be hard to define memory arrays as
a 'hint' on abstract arrays, though there are a few semantic issues.
For example, Maxima's object semantics for matrices are not quite
limpid. If you assign m2: m1, then m2 becomes the same object as m1,
and so modifications to m2 will change m1 and vice versa. However, m2:
m1.ident(...) makes m2 be a *copy* of m1, since Maxima constructs a
product matrix (it doesn't notice that ident(...) is the identity for
"."). As it happens, though, Maxima *does* recognize that 0 is the
identity for "+", and 1 is the identity for "^^", so m2: 0+m1 == m2:
m1^^1. But -- surprise! -- it doesn't recognize 1 as the multiplicative
identity: m1*1 is *not* the same object as m1.
And I suppose you could define matrices as lists-of-lists constrained to
be squared off (not ragged) -- but how do you express the constraint?
And it does seem ad hoc that they can be ragged in one dimension, but
not the other. That is, what is the value of transpose([1,[2,3]])? If
they can be ragged at the right and the bottom, why not the left and the
top? Why not arbitrarily sparse? Perhaps the APL/J people have answers
to things like this.
-s