MathGroup Archive 1996

[Date Index] [Thread Index] [Author Index]

Search the Archive

Complex Default

  • To: mathgroup at smc.vnet.net
  • Subject: [mg3031] Complex Default
  • From: evans at gte.net (Mark Evans)
  • Date: Wed, 24 Jan 1996 03:34:30 -0500
  • Organization: GTE Intelligent Network Services, GTE INS

The following was a suggestion I sent to Wolfram Research some time ago. 
I am curious what other people think of it.

Mark Evans
evans at gte.net


Gentlemen:

This suggestion relates to the use of complex numbers in Mathematica.

Mathematica should incorporate a global user setting that shuts off the
implicit assumption that undefined variables are complex numbers.  When
used, this preference setting would mean that instead of

In[1]:=
    realVar
Out[1]=
    realVar
In[2]:=
    Re[realVar]
Out[2]=
    Re[realVar]
In[3]:=
    Im[realVar]
Out[3]=
    Im[realVar]
In[4]:=
    Arg[realVar]
Out[4]=
    Arg[realVar]
In[5]:=
    Abs[realVar]
Out[5]=
    Abs[realVar]


we would get some simplifications with $ComplexDefault = False:


In[1]:=
    realVar
Out[1]=
    realVar
In[2]:=
    Re[realVar] (* known *)
Out[2]=
    realVar
In[3]:=
    Im[realVar] (* known *)
Out[3]=
    0
In[4]:=
    Arg[realVar] (* known *)
Out[4]=
    0
In[5]:=
    Abs[realVar]  (* could be +/- realVar; leave unknown *)
Out[5]=
    Abs[realVar]


I think you would implement this as a system variable, say $ComplexDefault
= [True | False].  The above outputs would correspond to $ComplexDefault =
True and $ComplexDefault = False, respectively.

It turns out that even when working with phasors, all of my undefined
variables are real.  Expressions only become complex when I personally
insert the imaginary unit.  These insertions are the only occurrence of
the imaginary unit in all of the computations.

Under such circumstances, I have been somewhat frustrated by Mathematica's
refusal to simplify expressions on the chance that a complex number might
be hiding behind symbols I know to be real.  Try, for example,
Conjugate[Exp[I x]].  Here was an interesting variant:

In[44]:=
Timing[Conjugate[Exp[I (kx^2 + ky^2)]]]
Out[44]=
                               2     2
                          I (kx  + ky )
{12.05 Second, Conjugate[E             ]}

Thus on an PowerMac 8100/80 MHz, it took Mathematica 12 seconds to find
out that it did not know how to negate the minus sign in a very simple
complex exponential.  This was with Roman Maeder's "ReIm" package already
loaded.  When I defined kx and ky to be real per his package, the time was
reduced to 3.5 seconds; still a long time for such a simple thing.  This
expression is like 2+2.  It should be a snap.

I suspect this is a problem in the start-up code that pattern-matches the
form of the input.  This is precisely my point, and it obtains more
generally in Mathematica:  we want to keep general-purpose symbolic code,
but we would also like to see greater convenience in manipulation of
expressions with known character.  I have perused the ComplexExpand.m
package and find that it is encumbered with far too much generality for my
purposes.  If you experiment with (symbolic) complex numbers, using
ComplexExpand[], Conjugate[], Re[], and so on, you will find that even
when it is possible to get a final answer, the wait is very long.

I have also examined Roman Maeder's "ReIm" package.  I like the idea of
using upvalues to clarify whether a symbol is real or complex.  However,
it is a debatable matter how these upvalues should be treated when
$ComplexDefault = False.  I suppose the way to handle this situation is to
stipulate symmetry.  Thus $ComplexDefault = False means that an undefined
symbol is REAL unless specifically upvalued into a COMPLEX number; and
$ComplexDefault = True means the symbol is COMPLEX unless specifically
upvalued into a REAL number.  It would cost a little bit more time in
terms of lookups, but tolerable amounts for completeness' sake.

I think this whole concept is philosophically sound as well.  The new
system variable would be a user-definable statement of his working
habits.  If you have qualms, consider the following.  Quaternions are a
generalization of complex numbers, but you don't initialize the
Mathematica kernel with the assumption that any undefined symbol can be a
quaternion.  You stop off at complex numbers, because they are far more
common than quaternions.  This being the case, why not allow the user to
terminate generalizing assumptions at the field of real numbers?  Real
numbers are far more common than complex numbers, just as complex numbers
are far more common than quaternions.

The workaround I have developed for now is simply to replace occurences of
Complex[a_,b_] with Complex[a,-b]:

conj[number_] := number /. {Complex[re_,im_] -> Complex[re, -im]}

The rules of complex algebra are such that this simple formula is
generally safe.  Thus (u1 + u2)* = u1* + u2*, (u1 u2)* = u1* u2*, (u1/u2)*
= (u1*/u2*).  In these cases the replacement rule works.  General
algebraic expressions can therefore be input to conj[] and will come out
all right.  (I would be interested if you think of any problematic cases.)

When $ComplexDefault = False, the kernel would still return complex roots,
eigenvalues, and the like when asked for them.  What we are talking about
here are the kernel's internal assumptions about undefined symbols.  You
might have the kernel issue messages each time the assumption could lead
to erroneous output for the sake of unwary users.  Personally, I would
Off[] this message in my Init.m file.

You might well have to implement additional C++ and Mathematica code
modules to handle special cases when arguments to various functions can be
assumed real.  However the resulting speed improvements would probably pay
for those efforts.


                    Mark Evans
                    evans at gte.net


==== [MESSAGE SEPARATOR] ====


  • Prev by Date: Matrix Algebra Weaknesses
  • Next by Date: Complex Default
  • Previous by thread: Re: Matrix Algebra Weaknesses
  • Next by thread: Complex Default