Re: fastest way to do pair-sum / make pair-list
- To: mathgroup at smc.vnet.net
- Subject: [mg23213] Re: [mg23170] fastest way to do pair-sum / make pair-list
- From: "Mark Harder" <harderm at ucs.orst.edu>
- Date: Mon, 24 Apr 2000 01:12:20 -0400 (EDT)
- Sender: owner-wri-mathgroup at wolfram.com
Winand wrote: >1. > >What is the most efficient way to calculate the sum >Sum f [ (x[[i]]-x[[j]])^2 ] , i<j?? > >Example: >I have a vector of real numbers: >lst = N[Range[100]]; >and a function operating on a number: >f[r2_]:=(r2-1.0)^2 > >Is > >Sum[ Sum[ f [ (lst[[i]]-lst[[j]])^2 ] , {j,i+1,Length[lst]}], >{i,1,Length[lst-1]}] > >the fastest way?? > >This kind of sum is very common in Molecular Modelling, where the total >energy of a system is often a sum of pair-energies, which only depend on >the distance between atoms. >I was surprised that I didn't find anything on sums over pairs in >Mathematica... > >2. > >What is the most efficient way to generate a list of pairs starting from >a list?? >Is there a standard Mathematica routine which does this? > >e.g. {a,b,c,d} ----> {{a,b},{a,c},{a,d},{b,c},{b,d},{c,d}} > >or {x1,x2,...} -----> { {xi,xj} ...} >with i<j > >Best solution I found was >topairs[lst_] := > Module[{l=Length[lst]}, > Map[(Sequence @@ #1) &, > Table[ lst [[{i, j}]], {i, 1, l - 1}, {j, i + 1, l}] > ] > ] > >Another possibility would be >topairs2[lst_] := > Module[{l = Length[lst]}, > Partition[ > Flatten[ > Table[ lst[[{i, j}]], {i, 1, l - 1}, {j, i + 1, l}] > ], 2 > ] > ] > >but this doesn't have the same effect if operating on a list of lists > topairs[{{a1, a2}, {b1, b2}, {c1, c2}}] >gives what we want, > topairs2[{{a1, a2}, {b1, b2}, {c1, c2}}] >not >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't know if I have the *most* efficient ways to do these things, but I took an interest in this & here are some results: First, it is not necessary to reiterate the Sum[] function (at least not in v4.0); look at the documentation & you will see that Sum accepts double indices, with the outermost index first. Your Sum[Sum[... method executes on my machine in .7+ seconds compared with the following: Timing[ Sum[ (lst[[i]] - lst[[j]])^2 , {i, 1, Length[lst - 1]}, {j, i + 1, Length[lst]} ] ] Out[484]= {0.29 Second, 8332500} In working on this problem at one point, I tried to avoid double indices althogether (by replacing one copy of the list with Drop[lst,i], and using some other Mathematica tricks (see below) ), but that method for calculating (lst[[i]] - lst[[j]])^2 was significantly slower than the above. As for creating the list of pairs, I created the following: In[477]:=lst = Range[1, 100]; In[465]:=ClearAll[Pairs ]; Pairs[lst1_List, lst2_List, len_Integer] /; (Length[lst1] == Length[lst2]) := Flatten[Table[Map[{lst1[[i]], #} &, Drop[lst2, i ] ], {i, len - 1} ], 1 ]; In[478]:=Timing[rslt = Pairs[lst, lst, Length[lst] ]; ] lr = Length[rslt] Out[478]={0.892 Second, Null} Out[479]=4950 This method produced the right result, but Table[], like Sum[] takes multiple indices, so I tried the following, even simpler method: In[487]:=ll = Length[lst2 ]; Flatten[Table[{lst2[[i]], lst2[[j]]}, {i, ll}, {j, i + 1, ll} ], 1 ] Out[488]={{a, b}, {a, c}, {a, d}, {a, e}, {b, c}, {b, d}, {b, e}, {c, d}, {c, e}, {d, e}} In[493]:=ll = Length[lst] rslt = Flatten[Table[{lst[[i]], lst[[j]]}, {i, ll}, {j, i + 1, ll} ], 1 ]; // Timing Length[rslt] Out[493]=100 Out[494]={0.12 Second, Null} Out[495]=4950 Lots better! You asked for a built-in function. Here's an add-on function called KSubsets[] : In[509]:=Needs["DiscreteMath`Combinatorica`"] KSubsets[lst2, 2] Out[509]={{a, b}, {a, c}, {a, d}, {a, e}, {b, c}, {b, d}, {b, e}, {c, d}, {c, e}, {d, e}} but run with lst=Range[1,100], it is almost 3x slower than "brute force" with Table[] ! : In[508]:=KSubsets[lst, 2]; // Timing Out[508]={0.33 Second, Null} I've often wondered if Mathematica can be used to do MM, since I'm a biophysical chemist myself. Let us know how you're doing with it. -mark harder harderm at ucs.orst.edu
- Follow-Ups:
- fastest way to do pair-sum / make pair-list
- From: Wagner Truppel <wtruppel@uci.edu>
- fastest way to do pair-sum / make pair-list