How to define an auto-Collect function

*To*: mathgroup at smc.vnet.net*Subject*: [mg7712] How to define an auto-Collect function*From*: "C. Woll" <carlw at u.washington.edu>*Date*: Wed, 2 Jul 1997 14:21:32 -0400 (EDT)*Sender*: owner-wri-mathgroup at wolfram.com

Hi all, I'm trying to define a function of two arguments, prd[a,b] which has the property that the sum of two prd's with the same first argument gets turned into a single prd where the second arguments get summed. That is prd[a_,b_]+prd[a_,c_] ^:= prd[a,b+c] The above definition will work, but since Plus is an orderless function, it takes forever. As an example, consider the following mma code: In[43]:= x=Sum[prd[a[i],b[i]],{i,100}]; y=Sum[prd[a[i],c[i]],{i,100}]; In[44]:= prd[a_,b_]+prd[a_,c_]^:=prd[a,b+c] In[45]:= z=x+y;//Timing Out[45]= {93.37 Second,Null} That's almost a hundred seconds (on a Pentium 90 PC)! Obviously, mma is comparing each term with every other term in the expression even though it only needs to compare adjacent terms (since Plus sorts them that way). So, is there a way to define an upvalue for the sum of two prd's, so that only adjacent elements are compared? My workaround for this problem is to define another "plus" function which is flat, but not orderless. In[46]:= SetAttributes[CirclePlus,Flat] prd[a_,b_]\[CirclePlus]prd[a_,c_]:=prd[a,b+c] CirclePlus[a__]:=Plus[a] contract[a_Plus]:=CirclePlus@@a contract[a_]:=a In[51]:= Clear[prd] In[52]:= Now, if I try to add x and y again, and then apply contract on the sum, I get w=contract[x+y];//Timing Out[52]= {0.39 Second,Null} In[53]:= z==w Out[53]= True So, I get the same result, only over 200 times faster. On the other hand, I now need to apply contract after each sum of prd's that I do. What I want to know is if anyone can come up with a way to collect the prd's just as quickly without requiring an additional contraction step. Carl Woll