Hoshen-Kopelman Algorithm MatLab Implementation - algorithm

First of all, I'm not 100% sure if Matlab is allowed on stack overflow; if I'm violating the rules tell me and I'll delete the question.
I'm currently studying percolation on a 2D surface (using a matrix for it), and I've written an algorithm that is able to check for percolation and label all cluster in a grid. The algorithm i wrote isn't very efficient and i've been tasked to implement the HK algorithm to do the same, more efficently since the HK doesn't "look behind".
FYI -> reticolo stands for grid, reticle
The "main" part of the program seems to work fine. Whenever i used my own way instead of the Find function i also found that in random grid where there aren't any cells that have BOTH up and left NN, everything works fine and the whole grid gets labelled correctly.
That also means that techincally the Union-Find part of the algorithm isn't really needed if the grid generated has cells that do not have both neighbors to the left and above, but that is clearly irrealistic.
What seems to be giving me problems is implementing correctly the Find function.
If anyone is able to help, I'd appreciate. Thanks
function A = HK(p,L)
if nargin == 0,0;
p = 0.55;
L = 4;
end
A.reticolo = rand(L)<p; % matrix field with prob p
A.label = zeros(L); % label field
A.prob = p; % prob field
idx = reshape(1:L^2, L, L);
nnl = [zeros(L,1) idx(:,1:L-1)]; % find near neighbor (NN) on the left
nnu = [zeros(1,L); idx(1:L-1,:)]; % find NN up
largest_label = 1;
for i = 1:L^2
left = i-L;
up = i-1;
if(A.reticolo(i) && ~A.label(i)) %If the site is coloured and has no label
%if it has NN-left and NN-up
if (nnu(i) && nnl(i) && A.reticolo(nnu(i)) && A.reticolo(nnl(i))) %#ok<*ALIGN>
% A.label(i) = min(A.label(i-L), A.label(i-1)); -> i tried
% a workaround that didn't really work
Union(left, up);
% If there's a NNL
elseif (nnl(i) && A.reticolo(nnl(i)))
A.label(i) = A.label(nnl(i)); %-> this is what i'm using
% since Find isn't working. This works for up and left cases.
% A.label(i) = Find(left); -> I should be using this instead
% If there's a NNU
elseif (nnu(i) && A.reticolo(nnu(i)))
A.label(i) = A.label(nnu(i));
%A.label(i) = Find(up) -> again, i should be using this instead of the line above
% If it doesn't have neighbours at all
else,
largest_label = largest_label +1;
A.label(i) = largest_label;
end
end
end
function F = Find(x)
while A.label(x) ~= x %here there seems to be a problem, that i don' get
x = A.label(x);
end
F = x;
end
function Union(x,y)
A.label(Find(x)) = Find(y);
end
end
And the errors I'm getting
Array indices must be positive integers or logical values.
Error in HK/Find (line 56)
while A.label(x) ~= x
Error in HK/Union (line 63)
A.label(Find(x)) = Find(y);
Error in HK (line 32)
Union(left, up);

Related

Increasing efficiency on a network randomization algorithm on Julia

My problem is the following. I have the adjacency matrix Mat for a neural network. I want to randomize this network in the sense that I want to choose 4 notes randomly (say i,j,p,q) such that i and p are connected (which means Mat[p,i] = 1) and j and q are connected AND i and q are not connected (Mat[q,j] = 0)and j and p are not connected. I then connect i and q and j and p and disconnect the previous nodes. In one run, I want to do this 10^6 times.
So far I have two versions, one using a for loop and one recursively.
newmat = copy(Mat)
for trial in 1:Niter
count = 0
while count < 1
i,j,p,q = sample(Nodes,4,replace = false) #Choosing 4 nodes at random
if (newmat[p,i] == 1 && newmat[q,j] == 1) && (newmat[p,j] == 0 && newmat[q,i] == 0)
newmat[p,i] = 0
newmat[q,j] = 0
newmat[p,j] = 1
newmat[q,i] = 1
count += 1
end
end
end
Doing this recursively runs about just as fast until Niter = 10^4 after which I get a Stack Overflow error. How can I improve this?
I assume you are talking about a recursive variant of the for trial in 1:Niter.
To avoid stack overflows like this, a general rule of thumb (in languages without tail recursion elimination) is to not use recursion unless you know the recursion depth will not scale more than logarithmically.
The cases where this is applicable is mostly algorithms that are like tree traversals, with a "naturally occuring" recursive structure. Your case of a simple for loop can be viewed as the degenerate variant of that, with a "linked list" tree, but is not a all natural.
Just don't do it. There's nothing bad about a loop for some sequential processing like this. Julia is an imperative language, after all.
(If you want to do this with a recursive structure for fun or exercise: look up trampolines. They allow you to write code structured as tail recursive, but with the allocation happening by mutation and on the heap.)
Instead of sampling 4 random nodes and hoping they happen to be connected, you can sample the starting nodes p and q, and look for i and j within the nodes that these are connected to. Here's an implementation of that:
function randomizeconnections(adjmatin)
adjmat = copy(adjmatin)
nodes = axes(adjmat, 2)
niter = 10
for trial in 1:niter
p, q = sample(nodes, 2, replace = false)
#views plist, qlist = findall(adjmat[p, :]), findall(adjmat[q, :])
filter!(i -> !in(i, qlist) && i != q, plist)
filter!(j -> !in(j, plist) && j != p, qlist)
if isempty(plist) || isempty(qlist)
#debug "No swappable exclusive target nodes for source nodes $p and $q, skipping trial $trial..."
continue
end
i = rand(plist)
j = rand(qlist)
adjmat[p, i] = adjmat[q, j] = false
adjmat[p, j] = adjmat[q, i] = true
end
adjmat
end
Through the course of randomization, it may happen that two nodes don't have any swappable connections i.e. they may share all their end points or one's ending nodes are a subset of the other's. So there's a check for that in the above code, and the loop moves on to the next iteration in that case.
The line with the findalls in the above code effectively creates adjacency lists from the adjacency matrix on the fly. You can instead do that in one go at the beginning, and work with that adjacency list vector instead.
function randomizeconnections2(adjmatin)
adjlist = [findall(r) for r in eachrow(adjmatin)]
nodes = axes(adjlist, 1)
niter = 10
for trial in 1:niter
p, q = sample(nodes, 2, replace = false)
plist = filter(i -> !in(i, adjlist[q]) && i != q, adjlist[p])
qlist = filter(j -> !in(j, adjlist[p]) && j != p, adjlist[q])
if isempty(plist) || isempty(qlist)
#debug "No swappable exclusive target nodes for source nodes $p and $q, skipping trial $trial..."
continue
end
i = rand(plist)
j = rand(qlist)
replace!(adjlist[p], i => j)
replace!(adjlist[q], j => i)
end
create_adjmat(adjlist)
end
function create_adjmat(adjlist::Vector{Vector{Int}})
adjmat = falses(length(adjlist), length(adjlist))
for (i, l) in pairs(adjlist)
adjmat[i, l] .= true
end
adjmat
end
With the small matriced I tried locally, randomizeconnections2 seems about twice as fast as randomizeconnections, but you may want to confirm whether that's the case with your matrix sizes and values.
Both of these accept (and were tested with) BitMatrix type values as input, which should be more efficient than an ordinary matrix of booleans or integers.

Creating fractal image in a plot MATLAB but the plot is empty

I am writing a function to create a fractal image in a plot. When I run my code, a plot pops up but it is empty. I think the issues lies somewhere in my if/elseif statements, but I am having a hard time finding it. My code is:
function [] = fractal(x, y, N)
close all
start = [x, y];
X = zeros(N+1,1);
Y = zeros(N+1,1);
X = start;
hold on
for i = 1:N
prob = rand;
if prob >= 0.01
X(i+1,:) = 0;
Y(i+1,:) = 0.16*y(1);
elseif prob == 0.02:0.86
X(i+1,:) = (0.85*x(i))-(0.04*y(i));
Y(i+1,:) = (-0.04*x(i))+(0.85*y(i))+1.6;
elseif prob == 0.87:0.94
X(i+1,:) = (0.2*x(i))-(0.26*y(i));
Y(i+1,:) = (0.23*x(i))+(0.22*y(i))+1.6;
elseif prob == 0.95:1.0
X(i+1,:) = (-0.15*x(i))+(0.28*y(i));
Y(i+1,:) = (0.26*x(i))+(0.24*y(i))+0.44;
plot(X(i,:),Y(i,:),'.','Markersize',1)
axis equal
end
end
end
When I run my code with
>> fractal(1,1,1000)
... a plot comes up but it is empty.
Yup... it's your if statements, but there are more issues with your code though but we will tackle those later. Let's first address your if statements. If you want to compare in a range of values for examples, you need use the AND (&&) statement. In addition, you should place your plot code outside of any if/elseif/else statement. You currently have it inside your last elseif statement so plot will only run if the last condition is satisfied.
To be explicit, if you wish to compare if a value is in between a certain range, do something like:
if (prob >= a && prob < b)
and for elseif:
elseif (prob >= a && prob < b)
a and b are the lower and upper limits of what you want to compare. This includes a but excludes b in the comparison.
I also have a several comments and recommendations with your current code in order to get this to work:
You run your function with a single x and y value, but you are trying to access this x and y in your for loop as if these were arrays. I'm assuming this is recursive in nature so you need to actually use X and Y in your if/else conditions instead of x and y.
Since you are using single values, it is superfluous to use : to access the second dimension. Just leave that out.
You create X and Y but then overwrite X to be the starting location as a 2D array... I think you meant to replace X and Y's first element with the starting location instead.
Your first if statement I think is incorrect. You'd want to access Y(i) not Y(1) no?... given the behaviour of your code thus far.
Your first condition will definitely mess things up for you. This is saying that as long as the value is greater than or equal to 0.01, execute that statement. Otherwise, try and execute the other conditions which may in fact never work because you are looking for values that are greater than 0.01 where the first condition already handles that for you. I assume you meant to check if it was less than 0.01 instead.
Doing value comparecondition array in MATLAB means that this statement is true provided that any one of the values in array matches the condition provided by value. This will have unintended side effects with your current code.
Make sure that your ranges covered for each if statement are continuous (i.e. no gaps or disconnects between ranges). Right now, you are checking for values in 0.01 intervals. rand generates random values between 0 and 1 exclusive. What if you had a value of 0.15? None of your if conditions handle this so you need to use what I talked about above.
You are most likely getting a blank plot because your MarkerSize attribute is very small.... you set it to 1 pixel. Unless you have super human vision, you can't really visualize this. Make the MarkerSize larger.
Use drawnow; after you plot to immediately update the results to screen.
Therefore, with refactoring your code, you should make it look something like this:
function [] = fractal(x, y, N)
close all
start = [x, y];
X = zeros(N+1,1);
Y = zeros(N+1,1);
%// Change - Initialize first elements of X and Y to be the starting positions
X(1) = start(1);
Y(1) = start(2);
hold on
for i = 1:N
prob = rand;
if prob <= 0.01 %// Change
X(i+1) = 0;
Y(i+1) = 0.16*Y(i); %// Change
elseif (prob > 0.01 && prob <= 0.86) %// Change
X(i+1) = (0.85*X(i))-(0.04*Y(i)); %// Change
Y(i+1) = (-0.04*X(i))+(0.85*Y(i))+1.6; %// Change
elseif (prob > 0.86 && prob <= 0.94) %// Change
X(i+1) = (0.2*X(i))-(0.26*Y(i)); %// Change
Y(i+1) = (0.23*X(i))+(0.22*Y(i))+1.6; %// Change
elseif (prob > 0.94 && prob <= 1.0) %// Change
X(i+1) = (-0.15*X(i))+(0.28*Y(i)); %// Change
Y(i+1) = (0.26*X(i))+(0.24*Y(i))+0.44; %// Change
end
%// Change - move outside of if/else blocks
%// Also make marker size larger
plot(X(i),Y(i),'.','Markersize',18); %// Change
axis equal
%// Add just for kicks
drawnow;
end
end
I now get this figure when I do fractal(1,1,1000):
.... cool fractal btw!

What is wrong with my Gradient Descent algorithm

Hi I'm trying to implement Gradient Descent algorithm for a function:
My starting point for the algorithm is w = (u,v) = (2,2). The learning rate is eta = 0.01 and bound = 10^-14. Here is my MATLAB code:
function [resultTable, boundIter] = gradientDescent(w, iters, bound, eta)
% FUNCTION [resultTable, boundIter] = gradientDescent(w, its, bound, eta)
%
% DESCRIPTION:
% - This function will do gradient descent error minimization for the
% function E(u,v) = (u*exp(v) - 2*v*exp(-u))^2.
%
% INPUTS:
% 'w' a 1-by-2 vector indicating initial weights w = [u,v]
% 'its' a positive integer indicating the number of gradient descent
% iterations
% 'bound' a real number indicating an error lower bound
% 'eta' a positive real number indicating the learning rate of GD algorithm
%
% OUTPUTS:
% 'resultTable' a iters+1-by-6 table indicating the error, partial
% derivatives and weights for each GD iteration
% 'boundIter' a positive integer specifying the GD iteration when the error
% function got below the given error bound 'bound'
%
% The error function
E = #(u,v) (u*exp(v) - 2*v*exp(-u))^2;
% Partial derivative of E with respect to u
pEpu = #(u,v) 2*(u*exp(v) - 2*v*exp(-u))*(exp(v) + 2*v*exp(-u));
% Partial derivative of E with respect to v
pEpv = #(u,v) 2*(u*exp(v) - 2*v*exp(-u))*(u*exp(v) - 2*exp(-u));
% Initialize boundIter
boundIter = 0;
% Create a table for holding the results
resultTable = zeros(iters+1, 6);
% Iteration number
resultTable(1, 1) = 0;
% Error at iteration i
resultTable(1, 2) = E(w(1), w(2));
% The value of pEpu at initial w = (u,v)
resultTable(1, 3) = pEpu(w(1), w(2));
% The value of pEpv at initial w = (u,v)
resultTable(1, 4) = pEpv(w(1), w(2));
% Initial u
resultTable(1, 5) = w(1);
% Initial v
resultTable(1, 6) = w(2);
% Loop all the iterations
for i = 2:iters+1
% Save the iteration number
resultTable(i, 1) = i-1;
% Update the weights
temp1 = w(1) - eta*(pEpu(w(1), w(2)));
temp2 = w(2) - eta*(pEpv(w(1), w(2)));
w(1) = temp1;
w(2) = temp2;
% Evaluate the error function at new weights
resultTable(i, 2) = E(w(1), w(2));
% Evaluate pEpu at the new point
resultTable(i, 3) = pEpu(w(1), w(2));
% Evaluate pEpv at the new point
resultTable(i, 4) = pEpv(w(1), w(2));
% Save the new weights
resultTable(i, 5) = w(1);
resultTable(i, 6) = w(2);
% If the error function is below a specified bound save this iteration
% index
if E(w(1), w(2)) < bound
boundIter = i-1;
end
end
This is an exercise in my machine learning course, but for some reason my results are all wrong. There must be something wrong in the code. I have tried debugging and debugging it and haven't found anything wrong...can someone identify what is my problem here?...In other words can you check that the code is valid gradient descent algorithm for the given function?
Please let me know if my question is too unclear or if you need more info :)
Thank you for your effort and help! =)
Here is my results for five iterations and what other people got:
PARAMETERS: w = [2,2], eta = 0.01, bound = 10^-14, iters = 5
As discussed below the question: I would say the others are wrong... your minimization leads to smaller values of E(u,v), check:
E(1.4,1.6) = 37.8 >> 3.6 = E(0.63, -1.67)
Not a complete answer but lets go for it:
I added a plotting part in your code, so you can see whats going on.
u1=resultTable(:,5);
v1=resultTable(:,6);
E1=E(u1,v1);
E1(E1<bound)=NaN;
[x,y]=meshgrid(-1:0.1:5,-5:0.1:2);Z=E(x,y);
surf(x,y,Z)
hold on
plot3(u1,v1,E1,'r')
plot3(u1,v1,E1,'r*')
The result shows that your algorithm is doing the right thing for that function. So, as other said, or all the others are wrong, or you are not using the right equation from the beggining.
(I apologize for not just commenting, but I'm new to SO and cannot comment.)
It appears that your algorithm is doing the right thing. What you want to be sure is that at each step the energy is shrinking (which it is). There are several reasons why your data points may not agree with the others in the class: they could be wrong (you or others in the class), they perhaps started at a different point, they perhaps used a different step size (what you are calling eta I believe).
Ideally, you don't want to hard-code the number of iterations. You want to continue until you reach a local minimum (which hopefully is the global minimum). To check this, you want both partial derivatives to be zero (or very close). In addition, to make sure you're at a local min (not a local max, or saddle point) you should check the sign of E_uu*E_vv - E_uv^2 and the sign of E_uu look at: http://en.wikipedia.org/wiki/Second_partial_derivative_test for details (the second derivative test, at the top). If you find yourself at a local max or saddle point, your gradient will tell you not to move (since the partial derivatives are 0). Since you know this isn't optimal, you have to just perturb your solution (sometimes called simulated annealing).
Hope this helps.

Code a linear programming exercise by hand

I have been doing linear programming problems in my class by graphing them but I would like to know how to write a program for a particular problem to solve it for me. If there are too many variables or constraints I could never do this by graphing.
Example problem, maximize 5x + 3y with constraints:
5x - 2y >= 0
x + y <= 7
x <= 5
x >= 0
y >= 0
I graphed this and got a visible region with 3 corners. x=5 y=2 is the optimal point.
How do I turn this into code? I know of the simplex method. And very importantly, will all LP problems be coded in the same structure? Would brute force work?
There are quite a number of Simplex Implementations that you will find if you search.
In addition to the one mentioned in the comment (Numerical Recipes in C),
you can also find:
Google's own Simplex-Solver
Then there's COIN-OR
GNU has its own GLPK
If you want a C++ implementation, this one in Google Code is actually accessible.
There are many implementations in R including the boot package. (In R, you can see the implementation of a function by typing it without the parenthesis.)
To address your other two questions:
Will all LPs be coded the same way? Yes, a generic LP solver can be written to load and solve any LP. (There are industry standard formats for reading LP's like mps and .lp
Would brute force work? Keep in mind that many companies and big organizations spend a long time on fine tuning the solvers. There are LP's that have interesting properties that many solvers will try to exploit. Also, certain computations can be solved in parallel. The algorithm is exponential, so at some large number of variables/constraints, brute force won't work.
Hope that helps.
I wrote this is matlab yesterday, which could be easily transcribed to C++ if you use Eigen library or write your own matrix class using a std::vector of a std::vector
function [x, fval] = mySimplex(fun, A, B, lb, up)
%Examples paramters to show that the function actually works
% sample set 1 (works for this data set)
% fun = [8 10 7];
% A = [1 3 2; 1 5 1];
% B = [10; 8];
% lb = [0; 0; 0];
% ub = [inf; inf; inf];
% sample set 2 (works for this data set)
fun = [7 8 10];
A = [2 3 2; 1 1 2];
B = [1000; 800];
lb = [0; 0; 0];
ub = [inf; inf; inf];
% generate a new slack variable for every row of A
numSlackVars = size(A,1); % need a new slack variables for every row of A
% Set up tableau to store algorithm data
tableau = [A; -fun];
tableau = [tableau, eye(numSlackVars + 1)];
lastCol = [B;0];
tableau = [tableau, lastCol];
% for convienience sake, assign the following:
numRows = size(tableau,1);
numCols = size(tableau,2);
% do simplex algorithm
% step 0: find num of negative entries in bottom row of tableau
numNeg = 0; % the number of negative entries in bottom row
for i=1:numCols
if(tableau(numRows,i) < 0)
numNeg = numNeg + 1;
end
end
% Remark: the number of negatives is exactly the number of iterations needed in the
% simplex algorithm
for iterations = 1:numNeg
% step 1: find minimum value in last row
minVal = 10000; % some big number
minCol = 1; % start by assuming min value is the first element
for i=1:numCols
if(tableau(numRows, i) < minVal)
minVal = tableau(size(tableau,1), i);
minCol = i; % update the index corresponding to the min element
end
end
% step 2: Find corresponding ratio vector in pivot column
vectorRatio = zeros(numRows -1, 1);
for i=1:(numRows-1) % the size of ratio vector is numCols - 1
vectorRatio(i, 1) = tableau(i, numCols) ./ tableau(i, minCol);
end
% step 3: Determine pivot element by finding minimum element in vector
% ratio
minVal = 10000; % some big number
minRatio = 1; % holds the element with the minimum ratio
for i=1:numRows-1
if(vectorRatio(i,1) < minVal)
minVal = vectorRatio(i,1);
minRatio = i;
end
end
% step 4: assign pivot element
pivotElement = tableau(minRatio, minCol);
% step 5: perform pivot operation on tableau around the pivot element
tableau(minRatio, :) = tableau(minRatio, :) * (1/pivotElement);
% step 6: perform pivot operation on rows (not including last row)
for i=1:size(vectorRatio,1)+1 % do last row last
if(i ~= minRatio) % we skip over the minRatio'th element of the tableau here
tableau(i, :) = -tableau(i,minCol)*tableau(minRatio, :) + tableau(i,:);
end
end
end
% Now we can interpret the algo tableau
numVars = size(A,2); % the number of cols of A is the number of variables
x = zeros(size(size(tableau,1), 1)); % for efficiency
% Check for basicity
for col=1:numVars
count_zero = 0;
count_one = 0;
for row = 1:size(tableau,1)
if(tableau(row,col) < 1e-2)
count_zero = count_zero + 1;
elseif(tableau(row,col) - 1 < 1e-2)
count_one = count_one + 1;
stored_row = row; % we store this (like in memory) column for later use
end
end
if(count_zero == (size(tableau,1) -1) && count_one == 1) % this is the case where it is basic
x(col,1) = tableau(stored_row, numCols);
else
x(col,1) = 0; % this is the base where it is not basic
end
end
% find function optimal value at optimal solution
fval = x(1,1) * fun(1,1); % just needed for logic to work here
for i=2:numVars
fval = fval + x(i,1) * fun(1,i);
end
end

Improving performance of interpolation (Barycentric formula)

I have been given an assignment in which I am supposed to write an algorithm which performs polynomial interpolation by the barycentric formula. The formulas states that:
p(x) = (SIGMA_(j=0 to n) w(j)*f(j)/(x - x(j)))/(SIGMA_(j=0 to n) w(j)/(x - x(j)))
I have written an algorithm which works just fine, and I get the polynomial output I desire. However, this requires the use of some quite long loops, and for a large grid number, lots of nastly loop operations will have to be done. Thus, I would appreciate it greatly if anyone has any hints as to how I may improve this, so that I will avoid all these loops.
In the algorithm, x and f stand for the given points we are supposed to interpolate. w stands for the barycentric weights, which have been calculated before running the algorithm. And grid is the linspace over which the interpolation should take place:
function p = barycentric_formula(x,f,w,grid)
%Assert x-vectors and f-vectors have same length.
if length(x) ~= length(f)
sprintf('Not equal amounts of x- and y-values. Function is terminated.')
return;
end
n = length(x);
m = length(grid);
p = zeros(1,m);
% Loops for finding polynomial values at grid points. All values are
% calculated by the barycentric formula.
for i = 1:m
var = 0;
sum1 = 0;
sum2 = 0;
for j = 1:n
if grid(i) == x(j)
p(i) = f(j);
var = 1;
else
sum1 = sum1 + (w(j)*f(j))/(grid(i) - x(j));
sum2 = sum2 + (w(j)/(grid(i) - x(j)));
end
end
if var == 0
p(i) = sum1/sum2;
end
end
This is a classical case for matlab 'vectorization'. I would say - just remove the loops. It is almost that simple. First, have a look at this code:
function p = bf2(x, f, w, grid)
m = length(grid);
p = zeros(1,m);
for i = 1:m
var = grid(i)==x;
if any(var)
p(i) = f(var);
else
sum1 = sum((w.*f)./(grid(i) - x));
sum2 = sum(w./(grid(i) - x));
p(i) = sum1/sum2;
end
end
end
I have removed the inner loop over j. All I did here was in fact removing the (j) indexing and changing the arithmetic operators from / to ./ and from * to .* - the same, but with a dot in front to signify that the operation is performed on element by element basis. This is called array operators in contrast to ordinary matrix operators. Also note that treating the special case where the grid points fall onto x is very similar to what you had in the original implementation, only using a vector var such that x(var)==grid(i).
Now, you can also remove the outermost loop. This is a bit more tricky and there are two major approaches how you can do that in MATLAB. I will do it the simpler way, which can be less efficient, but more clear to read - using repmat:
function p = bf3(x, f, w, grid)
% Find grid points that coincide with x.
% The below compares all grid values with all x values
% and returns a matrix of 0/1. 1 is in the (row,col)
% for which grid(row)==x(col)
var = bsxfun(#eq, grid', x);
% find the logical indexes of those x entries
varx = sum(var, 1)~=0;
% and of those grid entries
varp = sum(var, 2)~=0;
% Outer-most loop removal - use repmat to
% replicate the vectors into matrices.
% Thus, instead of having a loop over j
% you have matrices of values that would be
% referenced in the loop
ww = repmat(w, numel(grid), 1);
ff = repmat(f, numel(grid), 1);
xx = repmat(x, numel(grid), 1);
gg = repmat(grid', 1, numel(x));
% perform the calculations element-wise on the matrices
sum1 = sum((ww.*ff)./(gg - xx),2);
sum2 = sum(ww./(gg - xx),2);
p = sum1./sum2;
% fix the case where grid==x and return
p(varp) = f(varx);
end
The fully vectorized version can be implemented with bsxfun rather than repmat. This can potentially be a bit faster, since the matrices are not explicitly formed. However, the speed difference may not be large for small system sizes.
Also, the first solution with one loop is also not too bad performance-wise. I suggest you test those and see, what is better. Maybe it is not worth it to fully vectorize? The first code looks a bit more readable..

Resources