Vectorized Evaluation of a Function, Broadcasting and Element Wise Operations
<p>Given this...</p>

<p><a href="http://i.stack.imgur.com/FBePB.png" rel="nofollow"><img src="http://i.stack.imgur.com/FBePB.png" alt="enter image description here"></a></p>

<p>I have to explain what this code does, knowing that it performs the vectorized evaluation of F, using broadcasting and element wise operations concepts...</p>

<pre><code>def F(x_pos, alpha):
    D = x_pos.reshape(1,-1) - x_pos.reshape(-1,1)
    return (1./alpha) * (alpha.reshape(1,-1) * R(D)).sum(axis=1)
</code></pre>

<p><strong>My explanation is:</strong></p>

<p>In the first line of the function F receives x_pos and alpha as parameters (both numpy arrays), in the second line the matrix D is calculated by means of broadcasting (basic operations such as addition in arrays numpy are performed elementwise, ie, element by element, but it is also possible with arranys of different size if numpy can transform them into others of the same size, this conversion is called broadcasting), subtracting an array of order 1xN with another of order Nx1, resulting in the matrix D of order NxN containing x_j - x_1, x_j - x_2, etc. as elements, finally, in the last line the reciprocal of alpha is calculated (which clearly is an arrangement), where each element is multiplied by the sum of the R evaluation of each cell of the matrix D multiplied by alpha_j horizontally (due to axis = 1 in the argument)</p>

<p><strong>Questions:</strong></p>

<ol>
<li>Considering I'm new to Python, is my explanation OK?</li>
<li>The code has an error or not? Because I don't see that the "j must be different from 1, 2, ..., n" in each sum is taken into consideration in the code... and If it's in fact wrong... How can I fix the code so it do exactly the same thing as stated as in the image?</li>
</ol>

<p>Few comments/improvements/fixes could be suggested here.</p>

<p>1] The first step could be alternatively done with just introducing a new axis and subtracting with itself, like so -</p>

<pre><code>D = x_pos[:,None] - x_pos
</code></pre>

<p>In my opinion, this is a cleaner option. The performance benefit might be just marginal.</p>

<p>2] In the second line, I think it needs a fix as we need to avoid computations for the diagonal elements of <code>R(D)</code>. So, If I got that correctly, the corrected code would be -</p>

<pre><code>vals = R(D)
np.fill_diagonal(vals,0)
out = (1./alpha) * (alpha.reshape(1,-1) * vals).sum(axis=1)
</code></pre>

<p>Now, let's make the code a bit more idiomatic/cleaner.</p>

<p>At that line, we could write : <code>(alpha * vals)</code> instead of <code>alpha.reshape(1,-1) * vals</code>. This is because the shapes are already aligned for <code>broadcasting</code> as shown in a schematic diagram below -</p>

<pre><code>alpha :      n
vals  :  n x n
</code></pre>

<p>Thus, <code>alpha</code> would be automatically extended to <code>2D</code> with its elements broadcasted along the first axis for the length of <code>vals</code> and then elementwise multiplications being generated with it. Again, this is meant as a cleaner code.</p>

<p>There's a further performance improvement possible here with <code>(alpha.reshape(1,-1) * vals).sum(axis=1)</code> being replaceable with a <code>matrix-multiplicatiion</code> using <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html" rel="nofollow"><code>np.dot</code></a> as <code>alpha.dot(vals)</code>. The benefit on performance should be noticeable with this step.</p>

<p>So, the second step reduces to -</p>

<pre><code>out = (1./alpha) * alpha.dot(vals)
</code></pre>

python numpy vectorization elementwise-operations