High performance computation of mean 2D-Euclidian-distance - matlab

Let's say I have a position matrix P with dimensions 10x2, where the first column contains x values and second column the corresponding y values. I want the mean of the lengths of the positions. The way I have done this so far is with the following code:
avg = sum( sqrt( P(:,1).^2 + P(:,2).^2))/10);
I've been told that the integral function integral2 is much faster and more precise for this task. How can I use integral2 to compute the mean value?

Just so this question doesn't remain unanswered:
function q42372466(DO_SUM)
if ~nargin % nargin == 0
DO_SUM = true;
end
% Generate some data:
P = rand(2E7,2);
% Correctness:
R{1} = m1(P);
R{2} = m2(P);
R{3} = m3(P);
R{4} = m4(P);
R{5} = m5(P);
R{6} = m6(P);
for ind1 = 2:numel(R)
assert(abs(R{1}-R{ind1}) < 1E-10);
end
% Benchmark:
t(1) = timeit(#()m1(P));
t(2) = timeit(#()m2(P));
t(3) = timeit(#()m3(P));
t(4) = timeit(#()m4(P));
t(5) = timeit(#()m5(P));
t(6) = timeit(#()m6(P));
% Print timings:
disp(t);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Original method:
function out = m1(P)
if DO_SUM
out = sum( sqrt( P(:,1).^2 + P(:,2).^2))/max(size(P));
else
out = mean( sqrt( P(:,1).^2 + P(:,2).^2));
end
end
% pdist2 method:
function out = m2(P)
if DO_SUM
out = sum(pdist2([0,0],P))/max(size(P));
else
out = mean(pdist2([0,0],P));
end
end
% Shortened method #1:
function out = m3(P)
if DO_SUM
out = sum(sqrt(sum(P.*P,2)))/max(size(P));
else
out = mean(sqrt(sum(P.*P,2)));
end
end
% Shortened method #2:
function out = m4(P)
if DO_SUM
out = sum(sqrt(sum(P.^2,2)))/max(size(P));
else
out = mean(sqrt(sum(P.^2,2)));
end
end
% hypot
function out = m5(P)
if DO_SUM
out = sum(hypot(P(:,1),P(:,2)))/max(size(P));
else
out = mean(hypot(P(:,1),P(:,2)));
end
end
% (a+b)^2 formula , Divakar's idea
function out = m6(P)
% Since a^2 + b^2 = (a+b)^2 - 2ab,
if DO_SUM
out = sum(sqrt(sum(P,2).^2 - 2*prod(P,2)))/max(size(P));
else
out = mean(sqrt(sum(P,2).^2 - 2*prod(P,2)));
end
end
end
Typical result on my R2016b + Win10 x64:
>> q42372466(0) % with mean()
0.1165 0.1971 0.2167 0.2161 0.1719 0.2375
>> q42372466(1) % with sum()
0.1156 0.1979 0.2233 0.2181 0.1610 0.2357
Which means that your method is actually the best of the above, by a considerable margin! (Honestly - didn't expect that!)

Related

Use a variable outside the function in matlab

I've written the following function:
% This function plots the contours of likelihood values on the scatter plot of a 2 dimensional data.
function [xgrid,ygrid,Z,xy_matrix] = biVariateContourPlotsGMMCopula(givenData,gmmObject,~,numMeshPoints,x_dim,y_dim)
%INPUT: givenData (MxN, M=number of points, N=Dimension)
% : plo = binary variable (1 plot contour plot, 0 do not plot)
%OUTPUT: xgrid,ygrid,Z ( Z contains the likelihood values of the points defined by xgrid and ygrid)
%load general_info;
d = 2;
if nargin < 5
x_dim = 1;
y_dim = 2;
end
if x_dim == y_dim
hist(givenData(:,x_dim),10);
return;
end
numMeshPoints = min(numMeshPoints,256);
givenData = givenData(:,[x_dim y_dim]);
alpha = gmmObject.alpha;
mu = gmmObject.mu(:,[x_dim y_dim]);
sigma = gmmObject.sigma([x_dim y_dim],[x_dim y_dim],:) + 0.005*repmat(eye(d),[1 1 numel(alpha)]);
gmmObject = gmdistribution(mu,sigma,alpha);
bin_num = 256;
for j = 1:2
l_limit = min(gmmObject.mu(:,j))-3*(max(gmmObject.Sigma(j,j,:))^0.5);
u_limit = max(gmmObject.mu(:,j))+3*(max(gmmObject.Sigma(j,j,:))^0.5);
xmesh_inverse_space{j} = (l_limit:(u_limit-l_limit)/(bin_num-1):u_limit);
end
%if isempty(xmesh)||isempty(pdensity)||isempty(cdensity)
% Following for loop does the non-parameteric estimation of marginal % densities if not provided
for i = 1:d
currentVar = givenData(:,i);
[~,pdensity{i},xmesh{i}]=kde(currentVar,numMeshPoints);
pdensity{i}(pdensity{i}<0) = 0;
cdensity{i} = cumsum(pdensity{i});
cdensity{i} = (cdensity{i}-min(cdensity{i}))/(max(cdensity{i})-min(cdensity{i})); % scaling the cdensity value to be between [0 1]
end
[xgrid,ygrid] = meshgrid(xmesh{1}(2:end-1),xmesh{2}(2:end-1));
for k = 1:d
marginalLogLikelihood_grid{k} = log(pdensity{k}(2:end-1)+eps);
marginalCDFValues_grid{k} = cdensity{k}(2:end-1);
end
[marg1,marg2] = meshgrid(marginalLogLikelihood_grid{1},marginalLogLikelihood_grid{2});
[xg,yg] = meshgrid(marginalCDFValues_grid{1},marginalCDFValues_grid{2});
inputMatrix = [reshape(xg,numel(xg),1) reshape(yg,numel(yg),1)];
clear xg yg;
copulaLogLikelihoodVals = gmmCopulaPDF(inputMatrix,gmmObject,xmesh_inverse_space);
Z = reshape(copulaLogLikelihoodVals,size(marg1,1),size(marg1,2));
Z = Z+marg1+marg2;
Z = exp(Z);
% Getting the likelihood value from the log-likelihood
plot(givenData(:,1),givenData(:,2),'b.','MarkerSize',5);hold
[~,h] = contour(xgrid,ygrid,Z,[4e-6,4e-6]);
% Extract the (x, y) coordinates of the contour and concatenate them along the first dimension
xy_matrix = [];
for i = 1:length(h)
xy = get(h(i), 'XData');
x = xy(1, :);
y = xy(2, :);
xy_matrix = [xy_matrix, [x; y]];
end
% Print the concatenated matrix
disp(xy_matrix);
%title_string = ['GMCM fit (Log-Likelihood = ',num2str(logLikelihoodVal), ')'];
%title(title_string,'FontSize',12,'FontWeight','demi');
axis tight
however xy_matrix is not shown on the workspace.
How do I return the variable xy_matrix so that I can use it in another function?
Function call is inside a for loop as in below:
for i = 1:d
for j = 1:d
subplot(d,d,count); count = count+1;
[xgrid,ygrid,Z,xy_matrix] = biVariateContourPlotsGMMCopula(power_curve_reference_build_T2,gmcObject_bestfit,0,256,i,j);
end
end
So, when I'm including xy_matrix as a params in the function call, it generates the following error:
Have I missed anything here?
When you're calling the function with i==j==1 as parameters x_dim and y_dim, the function ends in the following if:
if x_dim == y_dim
hist(givenData(:,x_dim),10);
return;
end
The return values aren't defined at that point. If you define them in the beginning of the function, you won't get the error message.
function [xgrid,ygrid,Z,xy_matrix] = biVariateContourPlotsGMMCopula(givenData,gmmObject,~,numMeshPoints,x_dim,y_dim)
%INPUT: givenData (MxN, M=number of points, N=Dimension)
% : plo = binary variable (1 plot contour plot, 0 do not plot)
%OUTPUT: xgrid,ygrid,Z ( Z contains the likelihood values of the points defined by xgrid and ygrid)
%load general_info;
xgrid=0;
ygrid=0;
Z=0;
xy_matrix=0;
d = 2;
if nargin < 5
x_dim = 1;
y_dim = 2;
end
Below is a suggestion of some changes of your function call. The return values are saved in cells so that you don't overwrite them in the next iteration. The function is also not called when i==j==x_dim==y_dim.
xgrids={};
ygrids={};
Zs={};
xy_matrices={};
for i = 1:d
for j = 1:d
if i~=j
subplot(d,d,count); count = count+1;
[xgrids{i,j},ygrids{i,j},Zs{i,j},xy_matrices{i,j}] = biVariateContourPlotsGMMCopula(power_curve_reference_build_T2,gmcObject_bestfit,0,256,i,j);
end
end
end

Berlekamp Massey Algorithm for BCH simplified binary version

I am trying to follow Lin, Costello's explanation of the simplified BM algorithm for the binary case in page 210 of chapter 6 with no success on finding the error locator polynomial.
I'm trying to implement it in MATLAB like this:
function [locator_polynom] = compute_error_locator(syndrome, t, m, field, alpha_powers)
%
% Initial conditions for the BM algorithm
polynom_length = 2*t;
syndrome = [syndrome; zeros(3, 1)];
% Delta matrix storing the powers of alpha in the corresponding place
delta_rho = uint32(zeros(polynom_length, 1)); delta_rho(1)=1;
delta_next = uint32(zeros(polynom_length, 1));
% Premilimnary values
n_max = uint32(2^m - 1);
% Initialize step mu = 1
delta_next(1) = 1; delta_next(2) = syndrome(1); % 1 + S1*X
% The discrepancy is stored in polynomial representation as uint32 numbers
value = gf_mul_elements(delta_next(2), syndrome(2), field, alpha_powers, n_max);
discrepancy_next = bitxor(syndrome(3), value);
% The degree of the locator polynomial
locator_degree_rho = 0;
locator_degree_next = 1;
% Update all values
locator_polynom = delta_next;
delta_current = delta_next;
discrepancy_rho = syndrome(1);
discrepancy_current = discrepancy_next;
locator_degree_current = locator_degree_next;
rho = 0; % The row with the maximum value of 2mu - l starts at 1
for i = 1:t % Only the even steps are needed (so make t out of 2*t)
if discrepancy_current ~= 0
% Compute the correction factor
correction_factor = uint32(zeros(polynom_length, 1));
x_exponent = 2*(i - rho);
if (discrepancy_current == 1 || discrepancy_rho == 1)
d_mu_times_rho = discrepancy_current * discrepancy_rho;
else
alpha_discrepancy_mu = alpha_powers(discrepancy_current);
alpha_discrepancy_rho = alpha_powers(discrepancy_rho);
alpha_inver_discrepancy_rho = n_max - alpha_discrepancy_rho;
% The alpha power for dmu * drho^-1 is
alpha_d_mu_times_rho = alpha_discrepancy_mu + alpha_inver_discrepancy_rho;
% Equivalent to aux mod(2^m - 1)
alpha_d_mu_times_rho = alpha_d_mu_times_rho - ...
n_max * uint32(alpha_d_mu_times_rho > n_max);
d_mu_times_rho = field(alpha_d_mu_times_rho);
end
correction_factor(x_exponent+1) = d_mu_times_rho;
correction_factor = gf_mul_polynoms(correction_factor,...
delta_rho,...
field, alpha_powers, n_max);
% Finally we add the correction factor to get the new delta
delta_next = bitxor(delta_current, correction_factor(1:polynom_length));
% Update used data
l = polynom_length;
while delta_next(l) == 0 && l>0
l = l - 1;
end
locator_degree_next = l-1;
% Update previous maximum if the degree is higher than recorded
if (2*i - locator_degree_current) > (2*rho - locator_degree_rho)
locator_degree_rho = locator_degree_current;
delta_rho = delta_current;
discrepancy_rho = discrepancy_current;
rho = i;
end
else
% If the discrepancy is 0, the locator polynomial for this step
% is passed to the next one. It satifies all newtons' equations
% until now.
delta_next = delta_current;
end
% Compute the discrepancy for the next step
syndrome_start_index = 2 * i + 3;
discrepancy_next = syndrome(syndrome_start_index); % First value
for k = 1:locator_degree_next
value = gf_mul_elements(delta_next(k + 1), ...
syndrome(syndrome_start_index - k), ...
field, alpha_powers, n_max);
discrepancy_next = bitxor(discrepancy_next, value);
end
% Update all values
locator_polynom = delta_next;
delta_current = delta_next;
discrepancy_current = discrepancy_next;
locator_degree_current = locator_degree_next;
end
end
I'm trying to see what's wrong but I can't. It works for the examples in the book, but not always. As an aside, to compute the discrepancy S_2mu+3 is needed, but when I have only 24 syndrome coefficients how is it computed on step 11 where 2*11 + 3 is 25?
Thanks in advance!
It turns out the code is ok. I made a different implementation from Error Correction and Coding. Mathematical Methods and gives the same result. My problem is at the Chien Search.
Code for the interested:
function [c] = compute_error_locator_v2(syndrome, m, field, alpha_powers)
%
% Initial conditions for the BM algorithm
% Premilimnary values
N = length(syndrome);
n_max = uint32(2^m - 1);
polynom_length = N/2 + 1;
L = 0; % The curent length of the LFSR
% The current connection polynomial
c = uint32(zeros(polynom_length, 1)); c(1) = 1;
% The connection polynomial before last length change
p = uint32(zeros(polynom_length, 1)); p(1) = 1;
l = 1; % l is k - m, the amount of shift in update
dm = 1; % The previous discrepancy
for k = 1:2:N % For k = 1 to N in steps of 2
% ========= Compute discrepancy ==========
d = syndrome(k);
for i = 1:L
aux = gf_mul_elements(c(i+1), syndrome(k-i), field, alpha_powers, n_max);
d = bitxor(d, aux);
end
if d == 0 % No change in polynomial
l = l + 1;
else
% ======== Update c ========
t = c;
% Compute the correction factor
correction_factor = uint32(zeros(polynom_length, 1));
% This is d * dm^-1
dd_sum = modulo(alpha_powers(d) + n_max - alpha_powers(dm), n_max);
for i = 0:polynom_length - 1
if p(i+1) ~= 0
% Here we compute d*d^-1*p(x_i)
ddp_sum = modulo(dd_sum + alpha_powers(p(i+1)), n_max);
if ddp_sum == 0
correction_factor(i + l + 1) = 1;
else
correction_factor(i + l + 1) = field(ddp_sum);
end
end
end
% Finally we add the correction factor to get the new locator
c = bitxor(c, correction_factor);
if (2*L >= k) % No length change in update
l = l + 1;
else
p = t;
L = k - L;
dm = d;
l = 1;
end
end
l = l + 1;
end
end
The code comes from this implementation of the Massey algorithm

Solution of Burger equation by Newton-Raphson method in Matlab

I am solving Burger equation with Newton-Raphson method in Mathlab.
For the description of the problem see 1.
My problem is the following this code finds the solution upto time
$t=1$, but at this time a discontinuity develops and then the wave
moves forward (like a step function), but this code does not produce
correct solutions after time $t=1$.
Any suggestions or comments to improve the code.
Here is the Matlab code that I am using
function BurgerFSolve2
clc; clear;
% define a 1D mesh
a = -1; b = 3; Nx = 100;
x = linspace(a,b,Nx);
dx = (b-a)/Nx;
J = length(x);
% Iinitial condition
p_init = zeros(size(x));
p_init(x<=0) = 1;
p_init(x>0 & x<1)= 1-x(x>0 & x<1);
% storing results
P = zeros(length(p_init),3001);
P(:,1) = p_init;
% Boundary condition
pL = 1; pR = 0;
% solver
dt = 0.001;
t = 0;
T = zeros(1,3001);
c = dt/dx;
for i = 1:3000
t = t+dt;
T(i+1) = t;
options=optimset('Display','iter'); % Option to display output
p = fsolve(#(p) myfun1(p, pL, pR, c, J, P(:,i)), p_init, ...
options);
% Call solver
P(:,i+1) = p;
p_init = p;
figure(1);
plot(x, p, '-o');
title(['t= ' num2str(t) ' s']);
drawnow;
end
end
function F = myfun1(p, pL, pR, c, J, p_Old)
% Rewrite the equation in the form F(x) = 0
F(1) = p(1) + c*(p(1)^2 - p(1)*pL) - p_Old(1);
for i=2:J-1
F(i) = p(i) + c*(p(i)^2 - p(i-1)*p(i)) - p_Old(i);
end
F(J) = p(J) + c*(p(J)^2 - p(J-1)*p(J)) - p_Old(J);
end

Error in evaluating a function

EDIT: The code that I have pasted is too long. Basicaly I dont know how to work with the second code, If I know how calculate alpha from the second code I think my problem will be solved. I have tried a lot of input arguments for the second code but it does not work!
I have written following code to solve a convex optimization problem using Gradient descend method:
function [optimumX,optimumF,counter,gNorm,dx] = grad_descent()
x0 = [3 3]';%'//
terminationThreshold = 1e-6;
maxIterations = 100;
dxMin = 1e-6;
gNorm = inf; x = x0; counter = 0; dx = inf;
% ************************************
f = #(x1,x2) 4.*x1.^2 + 2.*x1.*x2 +8.*x2.^2 + 10.*x1 + x2;
%alpha = 0.01;
% ************************************
figure(1); clf; ezcontour(f,[-5 5 -5 5]); axis equal; hold on
f2 = #(x) f(x(1),x(2));
% gradient descent algorithm:
while and(gNorm >= terminationThreshold, and(counter <= maxIterations, dx >= dxMin))
g = grad(x);
gNorm = norm(g);
alpha = linesearch_strongwolfe(f,-g, x0, 1);
xNew = x - alpha * g;
% check step
if ~isfinite(xNew)
display(['Number of iterations: ' num2str(counter)])
error('x is inf or NaN')
end
% **************************************
plot([x(1) xNew(1)],[x(2) xNew(2)],'ko-')
refresh
% **************************************
counter = counter + 1;
dx = norm(xNew-x);
x = xNew;
end
optimumX = x;
optimumF = f2(optimumX);
counter = counter - 1;
% define the gradient of the objective
function g = grad(x)
g = [(8*x(1) + 2*x(2) +10)
(2*x(1) + 16*x(2) + 1)];
end
end
As you can see, I have commented out the alpha = 0.01; part. I want to calculate alpha via an other code. Here is the code (This code is not mine)
function alphas = linesearch_strongwolfe(f,d,x0,alpham)
alpha0 = 0;
alphap = alpha0;
c1 = 1e-4;
c2 = 0.5;
alphax = alpham*rand(1);
[fx0,gx0] = feval(f,x0,d);
fxp = fx0;
gxp = gx0;
i=1;
while (1 ~= 2)
xx = x0 + alphax*d;
[fxx,gxx] = feval(f,xx,d);
if (fxx > fx0 + c1*alphax*gx0) | ((i > 1) & (fxx >= fxp)),
alphas = zoom(f,x0,d,alphap,alphax);
return;
end
if abs(gxx) <= -c2*gx0,
alphas = alphax;
return;
end
if gxx >= 0,
alphas = zoom(f,x0,d,alphax,alphap);
return;
end
alphap = alphax;
fxp = fxx;
gxp = gxx;
alphax = alphax + (alpham-alphax)*rand(1);
i = i+1;
end
function alphas = zoom(f,x0,d,alphal,alphah)
c1 = 1e-4;
c2 = 0.5;
[fx0,gx0] = feval(f,x0,d);
while (1~=2),
alphax = 1/2*(alphal+alphah);
xx = x0 + alphax*d;
[fxx,gxx] = feval(f,xx,d);
xl = x0 + alphal*d;
fxl = feval(f,xl,d);
if ((fxx > fx0 + c1*alphax*gx0) | (fxx >= fxl)),
alphah = alphax;
else
if abs(gxx) <= -c2*gx0,
alphas = alphax;
return;
end
if gxx*(alphah-alphal) >= 0,
alphah = alphal;
end
alphal = alphax;
end
end
But I get this error:
Error in linesearch_strongwolfe (line 11) [fx0,gx0] = feval(f,x0,d);
As you can see I have written the f function and its gradient manually.
linesearch_strongwolfe(f,d,x0,alpham) takes a function f, Gradient of f, a vector x0 and a constant alpham. is there anything wrong with my declaration of f? This code works just fine if I put back alpha = 0.01;
As I see it:
x0 = [3; 3]; %2-element column vector
g = grad(x0); %2-element column vector
f = #(x1,x2) 4.*x1.^2 + 2.*x1.*x2 +8.*x2.^2 + 10.*x1 + x2;
linesearch_strongwolfe(f,-g, x0, 1); %passing variables
inside the function:
[fx0,gx0] = feval(f,x0,-g); %variable names substituted with input vars
This will in effect call
[fx0,gx0] = f(x0,-g);
but f(x0,-g) is a single 2-element column vector with these inputs. Assingning the output to two variables will not work.
You either have to define f as a proper named function (just like grad) to output 2 variables (one for each component), or edit the code of linesearch_strongwolfe to return a single variable, then slice that into 2 separate variables yourself afterwards.
If you experience a very rare kind of laziness and don't want to define a named function, you can still use an anonymous function at the cost of duplicating code for the two components (at least I couldn't come up with a cleaner solution):
f = #(x1,x2) deal(4.*x1(1)^2 + 2.*x1(1)*x2(1) +8.*x2(1)^2 + 10.*x1(1) + x2(1),...
4.*x1(2)^2 + 2.*x1(2)*x2(2) +8.*x2(2)^2 + 10.*x1(2) + x2(2));
[fx0,gx0] = f(x0,-g); %now works fine
as long as you always have 2 output variables. Note that this is more like a proof of concept, since this is ugly, inefficient, and very susceptible to typos.

Shidoku solver matlab code

I'm trying to write a Shidoku ( smaller and easier 4x4 variant of Sudoku) solver code in MATLAB.
I have found some soduko solver (9x9) but i could't revise them to be suitable for my problem. For example:
% Solving Sudoku Using Recursive Backtracking
function X = sudoku(X)
% SUDOKU Solve Sudoku using recursive backtracking.
% sudoku(X), expects a 9-by-9 array X.
% Fill in all “singletons”.
% C is a cell array of candidate vectors for each cell.
% s is the first cell, if any, with one candidate.
% e is the first cell, if any, with no candidates.
[C,s,e] = candidates(X);
while ~isempty(s) && isempty(e)
X(s) = C{s};
[C,s,e] = candidates(X);
end
% Return for impossible puzzles.
if ~isempty(e)
return
end
% Recursive backtracking.
if any(X(:) == 0)
Y = X;
z = find(X(:) == 0,1); % The first unfilled cell.
for r = [C{z}] % Iterate over candidates.
X = Y;
X(z) = r; % Insert a tentative value.
X = sudoku(X); % Recursive call.
if all(X(:) > 0) % Found a solution.
return
end
end
end
% ------------------------------
function [C,s,e] = candidates(X)
C = cell(9,9);
tri = #(k) 3*ceil(k/3-1) + (1:3);
for j = 1:9
for i = 1:9
if X(i,j)==0
z = 1:9;
z(nonzeros(X(i,:))) = 0;
z(nonzeros(X(:,j))) = 0;
z(nonzeros(X(tri(i),tri(j)))) = 0;
C{i,j} = nonzeros(z)';
end
end
end
L = cellfun(#length,C); % Number of candidates.
s = find(X==0 & L==1,1);
e = find(X==0 & L==0,1);
end % candidates
end % sudoku
Any help will be helpful.
Just reduce the problem dimensionality from 3 to 2 (I know now that it is said "9x9" instead of "3x3", but the important dimensional number for the puzzle is N=3):
% SHIDOKU Solve Shidoku using recursive backtracking.
% shidoku(X), expects a 4-by-4 array X.
function X = shidoku(X)
[C,s,e] = candidates(X);
while ~isempty(s) && isempty(e)
X(s) = C{s};
[C,s,e] = candidates(X);
end;
if ~isempty(e)
return
end;
if any(X(:) == 0)
Y = X;
z = find(X(:) == 0,1);
for r = [C{z}]
X = Y;
X(z) = r;
X = shidoku(X);
if all(X(:) > 0)
return;
end;
end;
end;
% ------------------------------
function [C,s,e] = candidates(X)
C = cell(4,4);
bi = #(k) 2*ceil(k/2-1) + (1:2);
for j = 1:4
for i = 1:4
if X(i,j)==0
z = 1:4;
z(nonzeros(X(i,:))) = 0;
z(nonzeros(X(:,j))) = 0;
z(nonzeros(X(bi(i),bi(j)))) = 0;
C{i,j} = transpose(nonzeros(z));
end;
end;
end;
L = cellfun(#length,C); % Number of candidates.
s = find(X==0 & L==1,1);
e = find(X==0 & L==0,1);
end % candidates
end % shidoku