# Define a custom variation on Sqrt[-1] ?

Posted 2 months ago
395 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 2 months 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 2 months ago
 Very helpful Neil, thank you. I was unaware of UpValues.
Posted 2 months 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 2 months 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