Matlab Array Division - arrays

I have been playing with matlab and was trying to calculate absolute relative error using two arrays. However, when I divide the two arrays, my resulting array has the same value throughout the array even though when I calculate the values by hand, they are not all the same. I was wondering why my resulting array shows the same answer for every value in the array.
Here is my code:
function [X] = absrelerror(A, B)
% Calculates absolute relative error for true value A and approximate value B.
A = linspace(sin(-pi/6), sin(pi/6), 50); %True
B = linspace(-pi/6, pi/6, 50); %Approximate
Y = abs((A-B) ./ A); %ARE equation
X = Y * 100; %convert to percent
end

I think you have approached the problem in a wrong way.
Here, the first elements of both A and B are constant. Also, the spacing between two elements of any of the vectors is also constant. Say, they are c and d where c = {A(50) - A(1)}/49 and d = {B(50) - B(1)}/49. Now, the nth value of Y is {A(1)*nc - B(1)*nd}/{A(1)*c} = {A(1)*c - B(1)*c}/A(1) which is constant. So, it's not surprising that MATLAB is giving a constant value in Y.
If I have understood correctly what you are trying to do, then you should do it in the following way:
%A = linspace(sin(-pi/6), sin(pi/6), 50); %True
B = linspace(-pi/6, pi/6, 50); %Approximate
%Y = abs((A-B) ./ A); %ARE equation
%X = Y * 100; %convert to percent
A = sin(B);
X = abs((A-B)./A) * 100;
fprintf('%f ', X)
The output is:
4.719755 4.330958 3.960262 3.607413 3.272170 2.954306 2.653606 2.369868 2.102903 1.852533 1.618593 1.400927 1.199394 1.013862 0.844209 0.690325 0.552111 0.429477 0.322344 0.230643 0.154315 0.093311 0.047592 0.017130 0.001903 0.001903 0.017130 0.047592 0.093311 0.154315 0.230643 0.322344 0.429477 0.552111 0.690325 0.844209 1.013862 1.199394 1.400927 1.618593 1.852533 2.102903 2.369868 2.653606 2.954306 3.272170 3.607413 3.960262 4.330958 4.719755

Related

How to recursively fill an array with functions?

So I'm trying to write a function to generate Hermite polynomials and it's doing something super crazy ... Why does it generate different elements for h when I start with a different n? So inputting Hpoly(2,1) gives
h = [ 1, 2*y, 4*y^2 - 2]
while for Hpoly(3,1) ,
h = [ 1, 2*y, 4*y^2 - 4, 2*y*(4*y^2 - 4) - 8*y]
( (4y^2 - 2) vs (4y^2 - 4) as a third element here )
also, I can't figure out how to actually evaluate the expression. I tried out = subs(h(np1),y,x) but that did nothing.
code:
function out = Hpoly(n, x)
clc;
syms y
np1 = n + 1;
h = [1, 2*y];
f(np1)
function f(np1)
if numel(h) < np1
f(np1 - 1)
h(np1) = 2*y*h(np1-1) - 2*(n-1)*h(np1-2);
end
end
h
y = x;
out = h(np1);
end
-------------------------- EDIT ----------------------------
So I got around that by using a while loop instead. I wonder why the other way didn't work ... (and still can't figure out how to evaluate the expression other than just plug in x from the very beginning ... I suppose that's not that important, but would still be nice to know...)
Sadly, my code isn't as fast as hermiteH :( I wonder why.
function out = Hpoly(n, x)
h = [1, 2*x];
np1 = n + 1;
while np1 > length(h)
h(end+1) = 2*x*h(end) - 2*(length(h)-1)*h(end-1);
end
out = h(end)
end
Why is your code slower? Recursion is not necessarily of Matlab's fortes so you may have improved it by using a recurrence relation. However, hermiteH is written in C and your loop won't be as fast as it could be because you're using a while instead of for and needlessly reallocating memory instead of preallocating it. hermiteH may even use a lookup table for the first coefficients or it might benefit from vectorization using the explicit expression. I might rewrite your function like this:
function h = Hpoly(n,x)
% n - Increasing sequence of integers starting at zero
% x - Point at which to evaluate polynomial, numeric or symbolic value
mx = max(n);
h = cast(zeros(1,mx),class(x)); % Use zeros(1,mx,'like',x) in newer versions of Matlab
h(1) = 1;
if mx > 0
h(2) = 2*x;
end
for i = 2:length(n)-1
h(i+1) = 2*x*h(i)-2*(i-1)*h(i-1);
end
You can then call it with
syms x;
deg = 3;
h = Hpoly(0:deg,x)
which returns [ 1, 2*x, 4*x^2 - 2, 2*x*(4*x^2 - 2) - 8*x] (use expand on the output if you want). Unfortunately, this won't be much faster if x is symbolic.
If you're only interested in numeric results of the the polynomial evaluated at particular values, then it's best to avoid symbolic math altogether. The function above valued for double precision x will be three to four orders of magnitude faster than for symbolic x. For example:
x = pi;
deg = 3;
h = Hpoly(0:deg,x)
yields
h =
1.0e+02 *
0.010000000000000 0.062831853071796 0.374784176043574 2.103511015993210
Note:
The hermiteH function is R2015a+, but assuming that you still have access to the Symbolic Math toolbox and the Matlab version is R2012b+, you can also try calling MuPAD's orthpoly::hermite. hermiteH used this function under the hood. See here for details on how to call MuPAD functions from Matlab. This function is a bit simpler in that it only returns a single term. Using a for loop:
syms x;
deg = 2;
h = sym(zeros(1,deg+1));
for i = 1:deg+1
h(i) = feval(symengine,'orthpoly::hermite',i-1,x);
end
Alternatively, you can use map to vectorize the above:
deg = 2;
h = feval(symengine,'map',0:deg,'n->orthpoly::hermite(n,x)');
Both return [ 1, 2*x, 4*x^2 - 2].

Skip some columns when searching a matrix in a loop

I have a matrix, c, and I want to search many times for the index of the positive minimum element
d = min(c(c>0));
[x,y] = find(c == d);
but in the next search I want it to skip the old y.
how to do it?
I want to use x and y in some other calculation.
also I want to find this d minimum just within specific columns in the matrix c like:
j from m+1 to n-1
please help
Define mask = zeros(size(c)); before the loop.
And before finding the minimum use,
newc = c + mask;
d = min(newc(newc>0));
[x,y] = find(newc == d);
mask(:,y) = NaN;
I think you can update the c matrix. I mean:
% In the loop, use it:
[x,y]=find(c==d);
c(:, y) = [];
If c matrix is important, you can use a temporary variable equals to c, instead of using c.

Generate MxN Matrix with MatLab Anonymous Function

Imagine for instance we have the following functions:
f = #(n) sin((0:1e-3:1) .* n * pi);
g = #(n, t) cos(n .^ 2 * pi ^2 / 2 .* t);
h = #(n) f(n) * g(n, 0);
Now, I would like to be able to enter an array of values for n into h and return a sum of the results for each value of n.
I am trying to be efficient, so I am avoiding the novice for-loop method of just filling out a pre-allocated matrix and summing down the columns. I also tried using arrayfun and converting the cell to a matrix then summing that, but it ended up being a slower process than the for-loop.
Does anyone know how I might do this?
The fact is the "novice" for-loop is going to be competitively as fast as any other vectorized solution thanks to improvements in JIT compilation in recent versions of MATLAB.
% array of values of n
len = 500;
n = rand(len,1);
% preallocate matrix
X = zeros(len,1001);
% fill rows
for i=1:len
X(i,:) = h(n(i)); % call function handle
end
out = sum(X,1);
The above is as fast as (maybe even faster):
XX = cell2mat(arrayfun(h, n, 'UniformOutput',false));
out = sum(XX,1);
EDIT:
Here it is computed directly without function handles in a single vectorized call:
n = rand(len,1);
t = 0; % or any other value
out = sum(bsxfun(#times, ...
sin(bsxfun(#times, n, (0:1e-3:1)*pi)), ...
cos(n.^2 * t * pi^2/2)), 1);

How do I find the indices of a given array A1, *any* of whose values are practically equivalent to *any* of the values of a second array A2?

By "practically equivalent", I mean that their distances are of order epsilon apart (or 0.000001). Equality in MATLAB often doesn't really work for long floating numbers.
If I simply do abs(A1 - A2) < 0.000001, it's not going to work since size(A1) != size(A2)
You can get the answer by calculating distance between two vectors using MATLAB's pdist2 function.
dist=pdist2(A1,A2);
minDist=min(dist,[],2);
indices_A1=minDist<=0.000001;
desired_A1=A1(indices_A1);
Not tested, but should work.
Since you care about a distance from any element to any element, you can create a distance matrix from the vectorized matrices and probe that for the distance threshold. Example:
A = rand(10, 4); % (example) matrix A
B = rand(3, 5); % matrix B of different size
minDist = 0.005;
Solution: Repeat vectorized matrices, column- and row-wise to get same size matrices and apply matrix-based distance estimation:
Da = repmat(A(:), 1, length(B(:))); % size 40 x 15
Db = repmat(B(:)', length(A(:)), 1); % size 40 x 15
DD = Da - Db;
indA = any(abs(DD) < minDist, 2);
The use of any() will give you logical indices to any value of A that is close to any value of B). You can directly index/return the elements of A using indA.
The matrix DD (as #Shai also points out) can be equivalently estimated through bsxfun
DD = bsxfun(#minus, A(:), B(:)');
In addition: you can map from row-index (corresponding to A elements) back to matrix A indices using:
[iA, jA] = ind2sub(size(A), indA);
Assert/test that all the returned values are less than minDist,e.g. using:
for k = 1:length(iA);
d(k) = min(min(abs(A(iA(k), jA(k)) - B)));
end
all(d < minDist)
(tested in Octave 3.6.2)

store data in array from loop in matlab

I want to store data coming from for-loops in an array. How can I do that?
sample output:
for x=1:100
for y=1:100
Diff(x,y) = B(x,y)-C(x,y);
if (Diff(x,y) ~= 0)
% I want to store these values of coordinates in array
% and find x-max,x-min,y-max,y-min
fprintf('(%d,%d)\n',x,y);
end
end
end
Can anybody please tell me how can i do that. Thanks
Marry
So you want lists of the x and y (or row and column) coordinates at which B and C are different. I assume B and C are matrices. First, you should vectorize your code to get rid of the loops, and second, use the find() function:
Diff = B - C; % vectorized, loops over indices automatically
[list_x, list_y] = find(Diff~=0);
% finds the row and column indices at which Diff~=0 is true
Or, even shorter,
[list_x, list_y] = find(B~=C);
Remember that the first index in matlab is the row of the matrix, and the second index is the column; if you tried to visualize your matrices B or C or Diff by using imagesc, say, what you're calling the X coordinate would actually be displayed in the vertical direction, and what you're calling the Y coordinate would be displayed in the horizontal direction. To be a little more clear, you could say instead
[list_rows, list_cols] = find(B~=C);
To then find the maximum and minimum, use
maxrow = max(list_rows);
minrow = min(list_rows);
and likewise for list_cols.
If B(x,y) and C(x,y) are functions that accept matrix input, then instead of the double-for loop you can do
[x,y] = meshgrid(1:100);
Diff = B(x,y)-C(x,y);
mins = min(Diff);
maxs = max(Diff);
min_x = mins(1); min_y = mins(2);
max_x = maxs(1); max_y = maxs(2);
If B and C are just matrices holding data, then you can do
Diff = B-C;
But really, I need more detail before I can answer this completely.
So: are B and C functions, matrices? You want to find min_x, max_x, but in the example you give that's just 1 and 100, respectively, so...what do you mean?

Resources