Calling a function on an array multiple times - arrays

Still trying to grasp around the basics of Matlab.
I have a function f, that takes as arguments a matrix A, and two numbers (max and delta).
I also have a function g that takes a matrix A and one number threshold and returns a matrix B, if the value of an element in A is bigger than or equal to threshold, the corresponding value in B should be 1, if it is smaller than or equal to -threshold, it should be -1, otherwise 0. The original matrix should not be changed in neither function f nor g.
I want function f to try different values for threshold in the call for g, and I want the results from each call to line up horizontally in a new matrix.
I'm not sure how to do this function f, I'm guessing the easiest way would be to create an array:
t1= [-threshold:delta:threshold];
but how do I call g for each value of the elements in the array and line them up in a new array?
function B = f(A, threshold, delta)
t1= [-threshold:delta:threshold];
%What to write here?
end
function B = g(A, threshold)
B=(A>=threshold)-(A<=-threshold);
end
If
A=[[-3:-1]' [1:3]']
Then
f(A, 2, 1)
should return the same matrix as the command [[-1 -1 0]' [0 1 1]' [-1 -1 0]' [0 1 1]']

What you want is a loop statement, a for loop would do well here.
As for lining the arrays side by side, simply create an array of the right size:
h = size(A,1);
w = size(A,2);
result = zeros( h , w*floor(2*threshold/delta) );
Then in each iteration index the correct section:
result(:,((i*w):((i+1)*w)+1) = g(A, -threshold+delta*i);
Although, I must say, it's somewhat of an odd way to store data, would be better to use a cell array, or a 3D matrix, something like this:
result = zeros( h , w , floor(2*threshold/delta) );
and
result(:,:,i+1) = g(A, -threshold+delta*i);

Related

Run-length encoding of a Repa array

I have a one-dimensional Repa array that consists of 0's and 1's and I want to calculate its run-length encoding.
E.g.: Turn [0,0,1,1,1,0,0,0,1,0,1,1] into [2,3,3,1,1,2] or something similar. (I'm using a list representation because of readability)
Ideally, I would like the run-length of the 1's and ignore the 0's.
So [0,0,1,1,1,0,0,0,1,0,1,1] becomes [3,1,2].
I would like the result to be a (Repa) array as well.
How can I do this using Repa? I can't use map or traverse since they only give me one element at a time. I could try to fold with some special kind of accumulator but that doesn't seem to be ideal and I don't know it it's even possible (due to monad laws).
I'm currently just iterating over the array and returning a list without using any Repa function. I'm working on Booleans instead of 1's and 0's but the algorithm is the same. I'm converting this list to a Repa Array afterwards.
runLength :: Array U DIM1 Bool -> [Length]
runLength arr = go ([], 0, False) 0 arr
where
Z :. n = extent arr
go :: Accumulator -> Int -> Array U DIM1 Bool -> [Length]
go !acc#(xs, c, b) !i !arr | i == n = if c > 0 then c:xs else xs
| otherwise =
if unsafeIndex arr (Z :. i)
then if b
then go (xs, c+1, b) (i+1) arr
else go (xs, 1, True) (i+1) arr
else if b
then go (c:xs, 0, False) (i+1) arr
else go (xs, 0, False) (i+1) arr

Matlab: creating 3D arrays as a function of 2D arrays

I want to create 3d arrays that are functions of 2d arrays and apply matrix operations on each of the 2D arrays. Right now I am using for loop to create a series of 2d arrays, as in the code below:
for i=1:50
F = [1 0 0; 0 i/10 0; 0 0 1];
B=F*F';
end
Is there a way to do this without the for loop? I tried things such as:
F(2,2) = 0:0.1:5;
and:
f=1:0.1:5;
F=[1 0 0; 0 f 0; 0 0 1];
to create them without the loop, but both give errors of dimension inconsistency.
I also want to perform matrix operations on F in my code, such as
B=F*F';
and want to plot certain components of F as a function of something else. Is it possible to completely eliminate the for loop in such a case?
If I understand what you want correctly, you want 50 2D matrices stacked into a 3D matrix where the middle entry varies from 1/10 to 50/10 = 5 in steps of 1/10. You almost have it correct. What you would need to do is first create a 3D matrix stack, then assign a 3D vector to the middle entry.
Something like this would do:
N = 50;
F = repmat(eye(3,3), [1 1 N]);
F(2,2,:) = (1:N)/10; %// This is 1/10 to 5 in steps of 1/10... or 0.1:0.1:5
First pre-allocate a matrix F that is the identity matrix for all slices, then replace the middle row and middle column of each slice with i/10 for i = 1, 2, ..., 50.
Therefore, to get the ith slice, simply do:
out = F(:,:,i);
Minor Note
I noticed that what you want to do in the end is a matrix multiplication of the 3D matrices. That operation is not defined in MATLAB nor anywhere in a linear algebra context. If you want to multiply each 2D slice independently, you'd be better off using a for loop. Doing this vectorized with native operations isn't supported in this context.
To do it in a loop, you'd do something like this for each slice:
B = zeros(size(F));
for ii = 1 : size(B,3)
B(:,:,ii) = F(:,:,ii)*F(:,:,ii).';
end
... however, examining the properties of your matrix, the only thing that varies is the middle entry. If you perform a matrix multiplication, all of the entries per slice are going to be the same... except for the middle, where the entry is simply itself squared. It doesn't matter if you multiple one slice by the transpose of the other. The transpose of the identity is still the identity.
If your matrices are going to be like this, you can just perform an element-wise multiplication with itself:
B = F.*F;
This will not work if F is anything else but what you have above.
Creating the matrix would be easy:
N = 50;
S = cell(1,N);
S(:) = {eye(3,3)};
F = cat(3, S{:});
F(2,2,:) = (1:N)/10;
Another (faster) way would be:
N = 50;
F = zeros(3,3,N);
F(1,1,:) = 1;
F(2,2,:) = (1:N)/10;
F(3,3,:) = 1;
You then can get the 3rd matrix (for example) by:
F(:,:,3)

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.

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