Re: (1) Symbolic complex algebra in mathematica
- To: mathgroup at yoda.ncsa.uiuc.edu
- Subject: Re: (1) Symbolic complex algebra in mathematica
- From: CAMERON at midd.cc.middlebury.edu
- Date: Mon, 26 Nov 90 13:04 EDT
In a recent posting, Ken Yip (yip-ken at CS.YALE.EDU) said: > I want to define a complex quantity "z = x + I y" so that > > Re[z] ==> x > Im[z] ==> y > Conjugate[z] ==> x - I y > > etc. > Mathematica doesn't seem to know how to do this even after I > define x and y to be real by "x/: RealQ[x] = True". > I tried to define some transformation rules, but then I couldn't find > a way to specify the pattern variable to be of type real AND symbol. (I took the liberty of reformatting.) This calls for an answer in three parts: > I want to define a complex quantity "z = x + I y" so that (...) etc. I have attached a tiny package below that does what is requested here, and a bit more. I wrote it some time ago for a friend. It relies on two other packages, "ReIm.m" and "Trigonometry.m", both of which are part of the standard Mma 1.2 distribution (in the "Algebra" subdirectory of the "Packages" directory). All I do is add a couple of extra simplification rules to the ones in those two packages, in order to cover a couple of cases that they seem to have missed. I also define a function "makereal" that makes it easy to declare a variable to be real. I've included a short session transcript below to illustrate what the package does. For the more advanced Mma users out there, I might point out that the only tricky part of writing this was avoiding the Mma bug that makes "Sqrt[a^2]" simplify to "a" for all expressions "a". This bug bit me in a preliminary version of the simplification rule for Abs. I had to add the condition "imagpart =!= 0" to that rule to keep Abs from disappearing around variables that had been declared to be real via "makereal". This happened because "Abs[a]" got rewritten to "Sqrt[ Re[a]^2 + Im[a]^2 ]", which then became "Sqrt[a^2]" (because if "a" is real then "Re[a]" is just "a" and "Im[a]" is 0), and this in turn got rewritten (incorrectly!) to "a". The extra condition prevents this rewriting rule for Abs from being applied to quantities that are already known to be real. > Mathematica doesn't seem to know how to do this even after I > define x and y to be real by "x/: RealQ[x] = True". "RealQ" is no longer used for this purpose, and hasn't been for ages -- ever since the release of Mma 1.2 in August of 1989. The function "makereal" in the package below does it in the currently approved fashion: "makereal[x]" results in "Re[x] ^:= x" and "Im[x] ^= 0". If you are still using Mma 1.1 or earlier then you might want to consider upgrading, as you are forgoing much functionality and enduring many bugs that have been fixed. (In fact, the code below won't work in 1.1, although it could be rewritten to do so -- which wouldn't help, since it relies on the 1.2 versions of "ReIm.m" and "Trigonometry.m".) > I tried to define some transformation rules, but then I couldn't find > a way to specify the pattern variable to be of type real AND symbol. If "RealQ" *were* still being used for this purpose, a pattern variable could be restricted to match only real symbols by a pattern of the form "x_Symbol?RealQ". We can define "RealQ" and use it this way -- here's an example: RealQ[x_] := Im[x]===0 foo[x_Symbol?RealQ] := StringJoin[ToString[x]," is a real symbol."] foo[x_Symbol] := StringJoin[ToString[x]," is not known to be real."] foo[x_] = "foo[] tests symbols only!"; Typing this into Mma gives the following results: In[9]:= makereal[a] In[10]:= foo[a] Out[10]= a is a real symbol. In[11]:= foo[z] Out[11]= z is not known to be real. In[12]:= foo[2+I] Out[12]= foo[] tests symbols only! Here's the package (I call it "extraReIm.m"): -------------------------------------------------------------------------- Needs["Algebra`ReIm`"] Begin["Algebra`ReIm`Private`"] `z `realpart `imagpart Unprotect[Abs,Conjugate] Conjugate[z_] := Block[ {realpart=Re[z],imagpart=Im[z]}, realpart - I imagpart /; (Head[realpart]=!=Re)||(Head[imagpart]=!=Im) ] Abs[z_] := Block[ {realpart=Re[z],imagpart=Im[z]}, Sqrt[ realpart^2 + imagpart^2 ] /; ((Head[realpart]=!=Re)||(Head[imagpart]=!=Im))&&(imagpart=!=0) ] Protect[Abs,Conjugate] `y Algebra`ReIm`makereal makereal[z_] := ( Re[z] ^:= z ; Im[z] ^= 0 ; ) makereal[z__] := ( makereal /@ {z} ; ) makereal[] = Null End[] Needs["Algebra`Trigonometry`"] Begin["Algebra`Trigonometry`Private`"] `x `y Unprotect[ComplexToTrig] ComplexToTrig[ Exp[x_+y__] ] := ComplexToTrig[Exp[x]] ComplexToTrig[Exp[y]] Protect[ComplexToTrig] End[] Null -------------------------------------------------------------------------- Here's a sample session to show what it does. First, in In[1], I load the package. Next, in In[2], I define "z" to be the expression "x + I y". In[3] and In[4] show what Conjugate and Abs do if they don't know that "x" and "y" are supposed to be real. In[5] uses "makereal" to make "x" and "y" act like reals. In[6] and In[7] show that Conjugate and Abs now do the right things. In[8] and In[9] show that complex exponentials can be converted to trigonometric expressions (this was a requirement of the friend for whom I wrote the code) and In[10]--In[12] show that the resulting expressions interact nicely with Re and Im (if the constituent variables are known to be real). -------------------------------------------------------------------------- Mathematica (NeXT) 1.2 (January 20, 1990) [With pre-loaded data] by S. Wolfram, D. Grayson, R. Maeder, H. Cejtin, S. Omohundro, D. Ballman and J. Keiper with I. Rivin and D. Withoff Copyright 1988,1989,1990 Wolfram Research Inc. In[1]:= << extraReIm.m In[2]:= z = x + I y Out[2]= x + I y In[3]:= Conjugate[z] Out[3]= Conjugate[x] + -I Conjugate[y] In[4]:= Abs[z] 2 2 Out[4]= Sqrt[(-Im[y] + Re[x]) + (Im[x] + Re[y]) ] In[5]:= makereal[x,y] In[6]:= Conjugate[z] Out[6]= x + -I y In[7]:= Abs[z] 2 2 Out[7]= Sqrt[x + y ] In[8]:= ComplexToTrig[ E^(3 I k d) ] Out[8]= Cos[3 d k] + I Sin[3 d k] In[9]:= result = ComplexToTrig[ E^(2 I k d + I omega t) ] Out[9]= (Cos[2 d k] + I Sin[2 d k]) (Cos[omega t] + I Sin[omega t]) In[10]:= makereal[d,k,omega,t] In[11]:= Re[result] Out[11]= Cos[2 d k] Cos[omega t] - Sin[2 d k] Sin[omega t] In[12]:= Im[result] Out[12]= Cos[omega t] Sin[2 d k] + Cos[2 d k] Sin[omega t] In[13]:= Quit -------------------------------------------------------------------------- Hope this is useful. --Cameron Smith Mathematica Consultant CAMERON at MIDD.BITNET --or-- cameron at midd.cc.middlebury.edu