In article <DCuwts.2vt at wri.com>,
Count Dracula <lk3a at kelvin.seas.virginia.edu> wrote:
>(Dave Wagner) wagner at bullwinkle.cs.Colorado.EDU writes:
>
>> For example, the following function checks a matrix
>> to see if it is diagonal:
>
>> DiagonalQ[m_] :=
>> And @@ Flatten[ MapIndexed[ #1==0 || Equal @@ #2 &, m, {2} ]]
>
>These functions check every member of the matrix and the || forces another
>condition check if the first equality check comes out false. For an n by n
>matrix, the number of checks could be as high as 2 n^2.
This argument is specious; any function for checking a matrix to see if
it is diagonal is O(n^2). The methods given by both you and Roman
Maeder (below) have much smaller constants of proportionality than
mine; I certainly can't deny that. But that is a quirk of the kernel's
implementation.
I agree that for efficiency reasons it is generally good practice to
operate on the largest chunks of data possible. And for production
code, a factor of 20 is certainly important. On the other hand, if
the need is for a "quick and dirty" check during the course of an
interactive session, I think that the MapIndexed technique is
so straightforward that any time lost due to its slow execution is
made up for in the quickness of the construction of working code.
If execution speed were all that mattered, we'd all be programming
in Fortran, not Mathematica (or worse, assembly language)!
Now what I have learned from this is that checking a matrix for a
regular structure of some sort is *not* the right application for
MapIndexed (not in production code, anyway), since for just about any
structure I can think of, I can construct a matrix having the given
structure and then compare it to the test subject (with a suitable
definition of "Equal"). This is Maeder's approach to the diagonal
matrix problem. It's a fast way to do it, but realize that it
trades memory for time. For most users, the former resource is more
precious than the latter.
Anyway, let's take as an axiom that I'm a lousy Mathematica programmer,
so that we can get back to the original point of my post, which is:
what is the motivation behind MapIndexed? I know that there usually
is a well-thought-out reason for the existence of any given Mathematica
function, although many of them are redundant. What problems did
the designers of Mathematica have in mind when they created this
function? I'm not asking for isolated examples; I'm interested in a
more conceptual answer. Or could it be that a good use for MapIndexed
is like pornography -- "I can't define it, but I know it when I see it"
(said by a former supreme court justice whose name I can't recall).
For reference, Kitis' and Maeder's solutions to the DiagonalQ
problem are reproduced below.
Levent Kitis' version:
> diagQ[m_?MatrixQ] /; SameQ @@ Dimensions[m] :=
> With[{n = Length[m]},
> Flatten[ MapIndexed[Drop, m] ] == Table[0, {n(n - 1)}]
> ]
Roman Maeder's version:
> dQ[m_?MatrixQ] /; SameQ @@ Dimensions[m] :=
> m == DiagonalMatrix[Transpose[m, {1, 1}]]
>)
>
Dave Wagner
Principia Consulting
(303) 786-8371
dbwagner at princon.com
http://www.princon.com/princon