14

I recently rediscovered a small package by Roman Maeder that tells Mathematica to automatically thread arithmetic and similar functions over expressions such as x == y. Link to Maeder's package.

First, to demonstrate, here's an example given by Maeder:

In[1]:= Needs["EqualThread`"]

Now proceed to use the threading behavior to solve the following equation for x 'by hand':

In[7]:= a == b Log[2 x]
In[8]:= %/b
Out[8]:= a/b == Log[2 x]

Now exponentiate:

In[9]:= Exp[%]
Out[9]= E^(a/b) == 2 x

And divide through by 2:

In[10]:= %/2
Out[10]= (E^(a/b))/2 == x

Q: From a design perspective, can someone explain why Mathematica is set to behave this way by default? Automatically threading seems like the type of behavior a Mathematica beginner would expect---to me, at least---perhaps someone can offer an example or two that would cause problems with the system as a whole. (And feel free to point out any mathematica ignorance...)

telefunkenvf14
  • 1,011
  • 7
  • 19
  • 1
    P.S.--Sometimes I wish it were possible to play around with old versions of MMA in order to get a better grasp on the how the overall design of the system has evolved. (quasi-objects, like the way MMA handles Series, or the statistical ModelObject's are of particular interest to me---both how they work and why they were designed the way they were, instead of some other approach.) I've only used v7-v8. – telefunkenvf14 Apr 18 '11 at 10:39
  • Nice question. I'm astonished that I never noticed this quirk in how MMA treats equations. – DavidC Apr 18 '11 at 10:53
  • 1
    +1, `Threadable` should definitely be made into an assignable attribute. MMA must keep an internal record of what functions are threadable with respect to what other functions (e.g. `Times` threads over `Plus` but not the other way round). – Timo Apr 18 '11 at 11:04

2 Answers2

11

Seems natural when thinking of arithmetic operations. But that is not always the case.

When I write

Boole[a==b]  

I don't want

Boole[a] == Boole[b]  

And that is what Maeder's package does.

Edit

Answering your comment below:

I noticed that Boole[] was added in v.5.2, whereas Maeder's package was authored for v.3. I guess the core of my question still revolves around the 'design' issue. I mean, how would one get around the issue you pointed out? To me, the clearest path would be declaring something about variables you're working with, no? -- What puzzles me is the way you can generally only do this with Assumptions (globally or as an option to Simplify, etc). Anyone else think it would be more natural to have a full set of numerical Attributes? (in this regard, the Constant Attribute is a tease)

My answer is by no means a critic to Maeder's package, which is nice, but a statement that it should not be the mainstream way to treat Equal[ ] in Mma.

Equal[ ] is a function, and not particularly easy to grasp at first:

  • returns True if lhs and rhs are identical
  • returns False if lhs and rhs are determined to be unequal by comparisons between numbers or other raw data, such as strings.
  • remains unevaluated when lhs or rhs contains objects such as Indeterminate and Overflow.
  • is used to represent a symbolic equation, to be manipulated using functions like Solve.

The intent of Maeder's package, which I understand is well aligned with yours, is to give to the expression lhs == rhs the same meaning and manipulation rules humans use when doing math.

In math, equality is an equivalence relation, imposing a partial order in a set, and an equation is an assertion that the expressions are related by this particular relation.

Compare these differences with other Mma "functions". Sin[x] is in Mma, and in usual math the same thing (well, almost), and the same can be said of most Mma beasts. There are a few Mma constructs, however, that do not hold that exact isomorphism to math concepts: Equal, SameQ, Equivalent, etc. They are the bridge from the math world to the programming world. They are not strict math concepts, but modified programming concepts to hold them.

Sorry if I got a little on the philosophical side.

HTH!

Dr. belisarius
  • 60,527
  • 15
  • 115
  • 190
  • I noticed that Boole[] was added in v.5.2, whereas Maeder's package was authored for v.3. I guess the core of my question still revolves around the 'design' issue. I mean, how would one get around the issue you pointed out? To me, the clearest path would be declaring something about variables you're working with, no? -- What puzzles me is the way you can generally only do this with Assumptions (globally or as an option to Simplify, etc). Anyone else think it would be more natural to have a full set of numerical Attributes? (in this regard, the Constant Attribute is a tease) – telefunkenvf14 Apr 22 '11 at 14:50
  • 1
    Philosophical is what I'm looking for here! The math vs. computer programming distinction is something that dawned on me after several months of learning MMA. This is partially why I advise my students against using TraditionalForm and Pallets, which (frustratingly) WRI likes to guide new users toward in several of the intro screencasts. This may create short-run gains--students get up and running--but I feel it traps many in beginner land, probably forever. Enough about pedagogy. Thanks for the reply. – telefunkenvf14 Apr 22 '11 at 18:22
8

I guess it is partly because the behavior can not be extended over to inequalities. And also because the behavior should make sense both when equalities become evaluated:

Would be nice:

In[85]:= Thread[Power[a == b, 2], Equal]

Out[85]= a^2 == b^2

In[86]:= Thread[Power[a == b, c == d], Equal]

Out[86]= a^c == b^d

but:

In[87]:= Thread[Power[a == b, c == d] /. {c -> 2, d -> 2}, Equal]

Out[87]= a^True == b^True
Sasha
  • 5,935
  • 1
  • 25
  • 33