Define a custom variation on Sqrt[-1] ?

Posted 1 year ago
2128 Views
|
6 Replies
|
3 Total Likes
|
 I'm looking to define a variable or function (let's call it I'), similar to I , such that I'^n takes on user-defined values.For conventional I : Table[I^n, {n, 10}] {I, -1, -I, 1, I, -1, -I, 1, I, -1} But I would like to define an I' such that Table[I'^n, {n, 10}] yields {-1, -I, 1, I, -1, -I, 1, I, -1,-I} ("phase-shifted I") or perhaps {-1, -1, I, I, -1, -1, I, I, -1,-1} , or {-1,-2,I,2I,1,2,-I,-2I,-1,-2}, or any arbitrary list. So whenever I'^n appears in a polynomial, each instance of I'^n is interpreted as the corresponding user-defined value.Any ideas? Thanks in advance.
6 Replies
Sort By:
Posted 1 year ago
 Bryan,To do this you need tp look at UpValues: ip /: ip^n_ := {1, 2, 3, 4}[[Mod[n, 4, 1]]] This defines an UpValue of Ip that matches the pattern ip^n. Then I lookup the value in the sequence based on the Mod operation. Regards,Neil
Posted 1 year ago
 Very helpful Neil, thank you. I was unaware of UpValues.
Posted 1 year ago
 Any thoughts on a workaround for ip, when not displayed as ip^1 ?Ideally, ip would return 1 (or the first element in the list), not ip.
Posted 1 year ago
 Bryan,The simplest thing that comes to mind is to do a replace rule at the end. For some reason I can't get optional arguments to work with UpValues. You need to let MMA apply the UpValue rule before the simplest case of just ip. For example, f = ip + 3* ip^2 + 4*ip^3 /. ip -> 1 will properly give 19 (given my strange definition for ip in the previous post)Another approach is to define a rule that will do what you want: In[1]:= myrule = ip^n___ : 1 :> {1, 2, 3, 4}[[Mod[n, 4, 1]]] In[2]:= f = ip + 3* ip^2 + 4*ip^3 /. myrule Out[2]= 19 I tried this same approach with the UpValues but it failed to work (I am reporting it as a bug). I tried: ip /: ip^n___:1 := {1, 2, 3, 4}[[Mod[n, 4, 1]]] This should have made the n optional with a default value of 1. Maybe someone knows another way to make this into a built-in rule. I'll report back what I get from Tech Support.Regards,Neil
 Yes, ReplaceAll ( /. ) would be my preferred method, but I am working with a very long polynomial, thousands or millions of terms long. Mathematica truncates or uses Short, so it only replaces some terms, not all. (this post)Appreciate the input Neil.
 Bryan,Short is only a display feature -- it does not affect the values or expressions in any way. Also, I usually try not to display such long outputs because its slow (use a semicolon) but no content is lost by the truncated display. If replaceAll does not get every term its because your replacement is adding new terms in. Mathematica will not miss any. (And Ive done many huge expressions!). I suggest you use ReplaceAllRepeated (//.) this will repeat until nothing changes.Here is an example: In[1]:= myrule = ip^n___ : 1 :> {1, ip, -1, -ip}[[Mod[n, 4, 1]]]; In[4]:= f = (1 - ip)^2 * (2 + 3*ip + 5* ip^2) Out[4]= (1 - ip)^2 (2 + 3 ip + 5 ip^2) In[6]:= g = Expand[f] Out[6]= 2 - ip + ip^2 - 7 ip^3 + 5 ip^4 In[7]:= g /. myrule Out[7]= 8 - 4 ip In[9]:= g //. myrule Out[9]= 4 Note that Out[7] contains ip but only because my definition (myrule) has ip in it. I read your other post and I agree with Daniel -- the answer from MMA is correct. Expand is a fast operation. The reason you see such slowdowns is that you are attempting to print ever increasingly complex expressions. Rerun your computation with a semicolon on the end of all the lines-- you will see a monumental speedup in your code. Besides you can't make sense of such a large output and it really brings the machine to its knees. To "explore" such long output look at chunks (myexpression[[1;;20]] to see the first 20 terms, etc.Regards Neil