Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Suppose you have a cubic box containing identical particles and you want to compute the distances between each particle and every other particle in the box without double-counting (i.e., if you've computed the distance between particles 1 and 2, you don't want to repeat the computation for particles 2 and 1 when looping through 2). In C-style languages you could do something like:

for ( int i = 0; i < nparticles - 1; i++ )
{
    for ( int j = i + 1; j < nparticles; j++ )
    {
       //calculate distance and some other stuff
    }
}

In Mathematica you could do the following:

  ParallelTable[Distance[coord[[i]], coord[[j]], z], 
                            {i, 1, nparticles - 1}, {j, i + 1, nparticles}]

Where Distance is a function that takes in the positions of two particles and a boxsize variable and spits-out the distance between them. Is there a better, more elegant Mathematica-way to achieve this? I've tried using Outer to no success.

To give a specific example:

coord = {{0.336384, 0.0132788, 0.895366}, {0.531722, 
  0.703736, -0.626689}, {1.3723, 0.191368, 
  0.930669}, {1.92434, -0.561288, 0.537316}, {2.48175, 1.34384, 
  0.368834}, {1.91778, 0.489024, -0.138269}, {3.22166, 1.46687, 
  1.16486}, {3.16976, -0.134968, 1.46946}, {3.31118, 0.625944, 
  0.0811552}, {4.39825, 1.03799, 
  0.985738}, {2.68123, -0.180248, -0.110539}, {4.68779, 0.22483, 
  0.0725717}, {5.41664, 0.982811, 0.491087}, {6.43321, 0.624075, 
  0.167138}, {6.60217, 1.59568, 2.19137}, {5.48321, -0.612703, 
  1.54037}, {0.275933, 1.73027, -0.319963}, {1.16899, 
  2.62176, -0.426422}, {0.895252, 2.30479, 0.546692}, {1.32435, 
  1.46099, -0.247962}, {2.438, 1.54727, -1.84394}, {2.84289, 2.47839, 
  0.487663}, {0.947902, 2.01877, 1.65962}, {4.27311, 1.66672, 
  1.82603}, {3.51098, 1.72636, 0.209131}, {2.53455, 2.68654, 
  1.45134}, {3.79154, 1.91726, 3.06622}, {5.59738, 1.69974, 
  1.26923}, {4.74771, 2.06686, 0.627377}, {5.8998, 1.90073, 
  0.269334}, {3.76603, 2.71011, 0.018981}, {6.52431, 1.09702, 
  1.0249}, {0.514549, 4.44605, -0.926816}, {1.18538, 
  3.8988, -0.291136}, {-1.03715, 3.48421, -0.126283}, {2.15475, 
  3.24303, -0.291715}, {1.96754, 2.39311, 0.152853}, {2.28468, 
  4.21156, 0.0596945}, {1.41851, 4.21297, 1.93538}, {1.77912, 3.13171,
   0.827817}, {3.40729, 3.67042, -0.335001}, {4.14912, 4.26701, 
  0.858455}, {3.42495, 3.43054, 0.832514}, {2.65226, 0.773315, 
  1.84478}, {4.50074, 3.62477, -0.228838}, {5.67743, 
  4.08899, -1.0032}, {4.98032, 2.56005, 1.60549}, {5.21301, 
  2.61515, -0.189593}, {-0.716714, 4.48811, -0.0695819}, {0.924003, 
  5.67242, 0.689366}, {1.02188, 6.33087, 1.77669}, {0.330792, 4.2462, 
  0.228187}, {1.79568, 5.98731, -0.447117}, {1.4538, 
  4.91975, -0.371939}, {1.49597, 5.34725, 1.68155}, {1.49152, 4.62994,
   0.659604}, {4.00242, 4.6745, -0.284203}, {3.10622, 4.50629, 
  0.728059}, {3.87473, 5.84693, 1.31431}, {2.98275, 5.88126, 
  0.697273}, {4.87938, 4.86575, 0.0826803}, {6.47473, 5.84112, 
  1.05569}, {4.76077, 5.92404, 0.606916}, {6.4309, 3.70755, 
  0.813097}, {0.104133, 0.851572, 3.46545}, {0.551016, 0.780983, 
  1.69373}, {-0.594108, 2.62214, 1.8779}, {0.708406, -0.797156, 
  2.9291}, {2.0969, -0.257719, 1.69345}, {3.93626, -0.163324, 
  0.657445}, {0.781078, 1.36067, 2.66083}, {3.8494, 0.656096, 
  1.86343}, {4.30525, -0.0180448, 2.46287}, {4.80984, 0.218372, 
  1.24748}, {2.76467, -0.0677178, 2.53374}, {4.58791, -0.856503, 
  3.05766}, {5.59133, -0.108523, 0.470608}, {7.29888, 0.209516, 
  2.63152}, {5.34566, 0.991826, 4.06735}, {4.31354, 0.951664, 
  2.75418}, {0.786024, 0.835163, 0.374784}, {1.49562, 0.756177, 
  2.29413}, {-1.31348, 3.36, 2.05473}, {1.96944, 1.82599, 
  2.15945}, {1.75072, 1.30223, 1.27227}, {2.25839, 3.48229, 
  2.18914}, {0.348436, 2.50653, 2.4213}, {1.82846, 1.37269, 
  3.04588}, {3.31408, 2.12509, 2.05064}, {3.41257, 3.28132, 
  2.45043}, {2.73336, 1.98305, 2.98785}, {5.36672, 1.01905, 
  2.02999}, {4.49376, 3.19686, 0.674299}, {5.6424, 2.95267, 
  0.927283}, {4.58006, 2.97117, 2.42488}, {5.10568, 1.9436, 
  2.47794}, {0.0359706, 2.12641, 1.14963}, {0.136018, 
  3.47913, -0.546182}, {0.324015, 3.19016, 1.53741}, {-0.364055, 
  3.30565, 2.57457}, {0.639834, 3.29517, 0.505645}, {2.21284, 3.99436,
   1.14992}, {1.21456, 3.05581, 2.09513}, {2.94578, 3.94601, 
  3.25965}, {3.09293, 3.99949, 1.79511}, {4.15348, 3.53126, 
  1.64667}, {3.17003, 4.95903, 2.7816}, {3.98937, 3.99651, 
  2.56071}, {4.79954, 4.84892, 3.01249}, {5.35644, 4.06114, 
  0.728884}, {6.14876, 5.29657, 1.8754}, {3.95394, 2.44156, 
  1.21713}, {0.00856939, 6.32042, 1.89394}, {-0.435331, 7.36044, 
  2.55351}, {0.19939, 5.0767, 3.33505}, {-0.347543, 4.13423, 
  1.7466}, {0.481867, 4.5129, 1.26472}, {2.29653, 4.50625, 
  2.36835}, {0.351039, 5.00868, 2.20155}, {1.53178, 3.70154, 
  2.98418}, {2.53732, 5.04177, 1.5255}, {3.72857, 4.78197, 
  1.72687}, {3.20208, 5.71681, 2.0526}, {5.32521, 6.78749, 
  2.3629}, {5.22618, 5.09716, 1.11705}, {5.94678, 7.11508, 
  1.51961}, {4.62847, 5.63837, 1.95489}, {6.28939, 4.82977, 
  0.848559}, {0.0461207, 1.93522, 3.25444}, {0.371978, -0.0986856, 
  3.58917}, {-0.461638, 1.25587, 4.47311}, {0.584499, -0.644038, 
  4.46688}, {2.48808, -0.420693, 3.44016}, {2.41666, 0.660956, 
  3.88881}, {1.55183, -0.235559, 2.81671}, {1.59083, -0.113905, 
  4.47863}, {3.60737, 0.284417, 3.38969}, {4.14487, 1.05219, 
  3.87699}, {4.27162, 0.351588, 4.8352}, {4.79354, 0.125734, 
  3.38844}, {5.27955, 0.079976, 4.41649}, {5.41948, 0.854351, 
  3.03103}, {5.22856, 0.775168, 5.21907}, {6.37806, 0.167375, 
  4.72112}, {-1.02014, 1.96112, 3.69853}, {-0.419047, 2.83171, 
  3.46298}, {-1.31457, 2.99279, 4.20992}, {2.44419, 0.358023, 
  4.95077}, {1.49318, 2.32455, 3.03509}, {0.432945, 4.0273, 
  3.6404}, {2.43741, 2.95397, 3.21087}, {3.14394, 1.4998, 
  3.86404}, {3.25509, 0.897897, 2.71971}, {4.45936, 3.20951, 
  3.55269}, {3.9792, 2.36403, 4.23043}, {4.70902, 1.5701, 
  4.75358}, {4.67827, 2.15833, 3.48814}, {5.44659, 2.80719, 
  3.058}, {5.12916, 3.09863, 5.67653}, {7.26935, 1.50287, 
  4.25862}, {-1.81989, 4.53932, 1.82345}, {0.556698, 3.93986, 
  2.51026}, {0.995211, 4.14387, 4.78229}, {0.27128, 3.07496, 
  4.3641}, {-0.718274, 3.82941, 3.61474}, {1.34653, 3.4258, 
  4.05185}, {0.666971, 2.94969, 3.26312}, {3.41411, 2.84055, 
  3.56064}, {2.67536, 5.2721, 3.64452}, {3.40383, 5.93004, 
  3.15271}, {4.1124, 6.19419, 3.95084}, {4.08112, 4.5837, 
  4.80518}, {4.98851, 3.90126, 2.90884}, {6.04449, 4.53769, 
  2.73099}, {5.45906, 5.56679, 2.58463}, {5.09465, 4.17775, 
  3.97109}, {-0.175458, 4.9133, 4.37999}, {0.880872, 5.07276, 
  4.35447}, {-0.131287, 5.91199, 5.42513}, {1.58653, 4.74081, 
  3.71834}, {1.36079, 5.03015, 2.71108}, {2.43226, 5.70154, 
  4.58147}, {1.42105, 5.88282, 3.64901}, {2.1028, 4.374, 
  4.68369}, {2.18209, 5.72639, 2.59178}, {5.44592, 6.0964, 
  3.55996}, {3.63535, 6.13173, 5.09292}, {4.66946, 5.20011, 
  4.01056}, {6.4787, 6.02617, 2.89552}, {6.054, 6.96222, 
  3.57906}, {6.46182, 5.96925, 3.94092}, {5.69617, 5.10088, 
  3.64138}, {0.615022, -0.027696, 5.42941}, {1.26461, 0.630006, 
  3.71384}, {0.883915, 1.42777, 5.47437}, {1.6792, 0.219376, 
  5.6289}, {2.59437, -0.684772, 5.60909}, {3.38078, 0.833026, 
  5.01004}, {2.84052, 0.573809, 5.90501}, {2.52553, 0.273467, 
  7.55756}, {4.41898, 0.696667, 5.85818}, {5.60858, 0.76452, 
  6.21228}, {5.74785, -1.1999, 7.01252}, {5.21135, -0.1117, 
  5.70978}, {4.66543, -0.919731, 4.87041}, {5.88829, 2.25357, 
  4.8022}, {6.3881, 1.00455, 5.545}, {6.22542, 0.0248028, 
  6.01928}, {0.586144, 0.520938, 4.41165}, {1.2068, 2.54395, 
  4.71756}, {0.436429, 2.33501, 5.52469}, {1.97207, 1.17024, 
  5.77531}, {2.25879, 3.04413, 5.01964}, {3.16137, 2.32338, 
  5.14988}, {2.02769, 2.28359, 5.84169}, {2.83295, 1.61539, 
  5.95777}, {3.8353, 1.69209, 5.8488}, {3.96829, 4.30873, 
  3.70322}, {2.99406, 2.69444, 6.18322}, {4.51472, 1.36171, 
  6.60083}, {3.63584, 3.42738, 4.39589}, {6.12614, 2.20446, 
  5.82261}, {4.02039, 2.78657, 5.66757}, {5.06004, 1.83423, 
  5.81263}, {1.10964, 3.21626, 5.41782}, {0.855608, 5.48462, 
  5.49}, {-0.571077, 3.27243, 5.29777}, {2.72265, 4.45985, 
  5.80695}, {1.48765, 1.09592, 4.7271}, {2.57181, 3.58383, 
  4.09092}, {1.85261, 3.99701, 5.63123}, {2.39584, 2.38821, 
  4.08817}, {3.14111, 4.4719, 4.37108}, {3.24159, 5.19853, 
  5.18419}, {2.9781, 5.51286, 6.43951}, {3.5866, 3.85079, 
  5.36787}, {4.57368, 3.59342, 4.68331}, {5.97774, 4.05604, 
  4.6439}, {4.63198, 4.10956, 5.6602}, {6.58299, 2.72811, 
  6.98548}, {-0.360483, 4.87033, 5.40138}, {1.66172, 6.00282, 
  5.1889}, {0.0873425, 5.97487, 6.85352}, {-0.0873903, 5.21734, 
  6.30516}, {2.00121, 5.14253, 5.51722}, {4.29976, 5.27308, 
  5.64666}, {0.988506, 6.73676, 6.59325}, {2.25374, 5.26316, 
  7.00213}, {3.74567, 6.67823, 6.34782}, {4.79574, 5.92614, 
  6.35025}, {3.28421, 6.66997, 4.2437}, {3.88385, 5.62567, 
  6.89584}, {3.46529, 5.45601, 4.13669}, {5.23652, 4.7538, 
  4.97666}, {5.72676, 5.96949, 4.96138}, {5.58535, 5.25335, 5.92877}}

coord contains the {x, y, z} coordinates of 256 particles.

Distance[x_, y_, z_] :=  If[# < z/2, #, Sequence @@ {}] & @
                  Sqrt[Total[((x - y) - z*Round[(x - y)/z])^2]]

Distance computes the periodic distance between two particles and only returns it if it meets a criterion.

share|improve this question
    
What do you consider "more elegant"? –  jVincent Feb 8 '13 at 23:53
    
@jVincent, anything better than Table –  RunnyKine Feb 8 '13 at 23:55
1  
Why use ParallelTable? Try Compile with Table or Do loop and approriate options. The only way to be even faster is to use C or Fortran for the loop and use MathLink. Fortran rules. –  Rolf Mertig Feb 9 '13 at 0:06
1  
This question is a nice addition to the discussion here: Alternatives to procedural loops and iterating over lists in Mathematica –  Jens Feb 9 '13 at 6:15
2  
Related: (8272) –  Mr.Wizard Feb 9 '13 at 7:28

3 Answers 3

up vote 10 down vote accepted

How about this (final version with improvement suggested by jVincent):

mutualDistances[coords_,distF_] :=
    distF @@@ Subsets[coords, {2}]

?

In your case, you should use distf = Distance[##,z]& with whatever your z is. The result you get corresponds to what you'd get with your Table code, if you additionally Flatten it.

share|improve this answer
    
@jVincent Yes, that's true. I have a habit of working with indices,but here they don't bring much of an advantage. Will edit your suggestion in, thanks. –  Leonid Shifrin Feb 9 '13 at 0:27
    
This is clearly an elegant way. I'm just waiting to see other clever solutions before I accept it. Thanks for your input, I learned something new today. –  RunnyKine Feb 9 '13 at 0:38
    
@RunnyKine Right, it is a good habit to not accept immediately. This would motivate others to contribute more answers. –  Leonid Shifrin Feb 9 '13 at 0:39

In cases like this, you could also use SparseArray. The equivalent of your Table command would be:

dist = SparseArray[{i_, j_} :> Distance[coord[[i]], coord[[j]], 3] /; i > j, 256];

where Distance and coord are as defined in your question, and 3 is some arbitrary value I chose for z.

You can get all the non-zero values as

dist["NonzeroValues"] 

and you'll have Null wherever Distance returned a Sequence[]. You can remove this by either defining your sequence to return 0 (in which case, you can simply use dist["NonzeroPositions"] to get the pairs for which something was returned), or via a replacement: /. Null -> Sequence[]

share|improve this answer
    
Another elegant solution. Thanks. –  RunnyKine Feb 9 '13 at 0:47

I suppose subsets is what you're looking for. Similar to Leonid's answer:

Select[EuclideanDistance @@@ Subsets[coords, {2}], # < z/2 &]

Another function along these lines is Outer, which operates on the Cartesian product of two lists. (Tuples and Permutations are also useful).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.