Say I have two matrices (or, as in my case, higher order tensors) $A,B$, and I want to solve the equation $A=B$. To do so , I need a list of equations that equate entry-wise the elements of $A$ and $B$ (then I can pass this list to Solve or DSolve or whatnot). Is there a simpler way to get this list than

Thread /@ Thread[A == B] // Flatten

Because this only works for matrices and I need to add another Thread for each rank. I'm sure some of you code-golfers will come up with somehting elegant and unreadable...

7 Answers
7

this evaluates A==B, then maps Flatten over the result; is this what you intended? (compare Thread[Flatten /@ (a \[Equal] b)] // Trace to the trace of the code I give in my answer to see what I mean)
–
aclMar 19 '12 at 22:26

Yes, to be consistent with what he was doing for matrices
–
RojoMar 19 '12 at 22:27

1

Right, I see. He has in mind a symbolic matrix on the left hand side, because this does not work for both numerical (also this is what it seems from his motivation).
–
aclMar 19 '12 at 22:29

Yeah. RM's second solution is the only "bullet-proof" one so far. Your solution doesn't work for arbitrary dimensional tensors unless you manually change the 2
–
RojoMar 19 '12 at 22:34

This should work regardless of whether it is numeric or symbolic or what the order of the tensor is.

An answer that I had earlier was to exploit the Listable attribute of Times and then replace with Equal (only for symbolic matrices/tensors) as:

mat1 mat2 /. Times -> Equal // Flatten

However, as Rojo pointed out, if the symbolic expressions themselves have Times inside them, the above won't work. The way around is to use his suggestion and create function that has the Listable attribute and does the job:

Now your first one is cuute but daangerous. What if your matrixes have symbolic expressions with Timesinside?
–
RojoMar 19 '12 at 22:36

Thanks for the answer, but the first one doesn't work for me (even if I replace the comma with an ==) and the second works only for matrices (and not for higher rank tensors)
–
yohbsMar 19 '12 at 22:38

The following method is broken for packed arrays. It works for many functions besides Equal, but some functions such as Equal, Unequal, and SameQ behave unexpectedly with regard to the Listable attribute and packed arrays. I am exploring this further. A far less clean but valid substitute is:

Somewhat more efficient is to use the undocumented function Internal`InheritedBlock which behaves as though one did SetAttributes[Equal, Listable] directly, saving an extra step of evaluation that occurs with the method above.

I never think of block — Is there a reason to choose/performance difference between changing (temporarily) Equal to have the Listable attribute and defining a function that is Listable and does the same like in mine?
–
The Toad♦Mar 20 '12 at 0:02

@R.M A simple test shows that (for some cases at least) my method is more efficient. MapThread is slightly ahead but also less automatic in a way. I think that using InheritedBlock is arguably the cleanest method, because it directly sets the Listable attribute on the active function.
–
Mr.Wizard♦Mar 20 '12 at 0:06

Mr.Wizard, I would also think that your InheritedBlock solution should be the most efficient, elegant, robust, and general solution of all so far. The MapThread one only works for matrices. However, there's a behaviour I'm not understanding... Got a min?
–
RojoMar 20 '12 at 0:43

The above equates the matrices element by element. To see this, define

c = Array[Subscript[d, #1, #2] &, {4, 4}]

then try the code I gave, ie, MapThread[Equal, {c, b}, 2] and your code, Thread /@ Thread[c == b] // Flatten; they give the same answer. But yours does not work for numeric matrices: Thread /@ Thread[a \[Equal] b] // Flatten errors. To see why, trace what is happening: Thread /@ Thread[a == b] // Trace and you see it first evaluates a==b, then threads. So, if one of the matrices is symbolic, this works OK as the Equal returns unevaluated, then gets threaded; but if both are numeric, the Equal[a,b] evaluates to False, and then there's nothing to thread or flatten.

Thus, your code and Rojo's answer rely on one of the matrices being symbolic so that the Equal[a,b] part remains unevaluated. They don't equate a and b elementwise if they are numeric (not that this matters for what you want to do; I just thought it was worth mentioning).

Mathematica is a registered trademark of Wolfram Research, Inc. While the mark is used herein with the limited permission of Wolfram Research, Stack Exchange and this site disclaim all affiliation therewith.