handle function Matlab - arrays

I'm starting to use functions handles in Matlab and I have a question,
what Matlab computes when I do:
y = (0:.1:1)';
fun = #(x) x(1) + x(2).^2 + exp(x(3)*y)
and what Matlab computes when I do:
fun = #(x) x + x.^2 + exp(x*y)
Because I'm evaluating the Jacobian of these functions (from this code ) and it gives different results. I don't understand the difference of putting x(i) or only x

Let's define a vector vec as vec = [1, 2, 3].
When you use this vec in your first function as results = fun(vec), the program will take only the particular elements of the vector, meaning x(1) = vec(1), x(2) = vec(2) and x(3) = vec(3). The whole expression then will look as
results = vec(1) + vec(2).^2 + exp(vec(3)*y)
or better
results = 1 + 2^2 + exp(3*y)
However, when you use your second expression as results = fun(vec), it will use the entire vector vec in all the cases like this
results = vec + vec.^2 + exp(vec*y)
or better
results = [1, 2, 3] + [1^2, 2^2, 3^2] + exp([1, 2, 3]*y)
You can also clearly see that in the first case, I don't really need to care about matrix dimensions, and the final dimensions of the results variable are the same as the dimensions of your y variable. This is not the case in the second example, because you multiply matrices vec and y, which (in this particular example) results in error, as the vec variable has dimensions 1x3 and the y variable 11x1.

If you want to investigate this, I recommend you split this up into subexpressions and debug, e.g.
f1 = #(x) x(1);
f2 = #(x) x(2).^2;
f3 = #(x) exp(x(3)*y);
f = #(x) f1(x) + f1(x) + f3(x)
You can split it up even further if any subexpression is unclear.
The distinction is that one is an array array multiplication (x * y, I'm assuming x is an array with 11 columns in order for the matrix multiplication to be consistent) and the other is a scalar array multiplication (x(3) * y). The subscript operator (n) for any matrix extracts the n-th value from that matrix. For a scalar, the index can only be 1. For a 1D array, it extracts the n-th element of the column/row vector. For a 2D array, its the n-th element when traversed columnwise.
Also, if you only require the first derivative, I suggest using complex-step differentiation. It provides reduced numerical error and is computationally efficient.

Related

Storing the sorted indices of a 2-D array in MATLAB?

Say I have an n x n array A. Is there a "nice" way to do the following?
A_flat = reshape(A, [1, numel(A)]);
[dummy, A_index] = sort(A, 'descend');
A_row = mod(A_index - 1, size(A, 1)) + 1;
A_col = floor((A_index - 1) / size(A, 1));
By "nice", I mean am looking for a way that doesn't use for-loops, doesn't use mod/floor, and is efficient. (I'm new to MATLAB, and still not sure what functions exist and what kinds of things to expect built-in functions for.)
If I am understanding your code correctly, you are given a 2D matrix and it is your task to sort the values in this 2D matrix. The way you are currently performing this is to unroll the values into a vector, sort this vector and calculate where the corresponding 2D locations would be.
That can be achieved by ind2sub. When you are using reshape, the unrolling into the vector is done in a column-major format so that columns of the matrix are stacked together. When performing the sorting, this is also doing using the column-major layout. In a similar fashion, ind2sub takes in column-major indices and produces the equivalent row and column locations that map to each index.
The second output of sort would give you the locations of where each value would appear in the sorted result in a column-major format. Just take this result and directly use ind2sub:
%// Your code
A_flat = reshape(A, [1, numel(A)]);
[dummy, A_index] = sort(A, 'descend');
%// New
[A_row, A_col] = ind2sub(size(A), A_index);

Passing a 1xn array into a function handle instead of individual values for Matlab?

I'm trying to find a way to pass a 1xn array into a function handler with n being the number of variables in the function so let's suppose I declare a handler as such:
U = #(x, y) x^2 + 2*y^2
and plugged in:
U(1, 2)
ans =
9
Is there some way I can do something similar to this instead?
a = [1, 2]
U(a)
ans =
9
Yes you can;
U = #(x, y) x^2 + 2*y^2;
a = {1, 2};
U(a{:})
When you expand the contents of a cell {:} it expands as the separate values stored in the cell. This is different from myMatrix(...) or myCell(...) which both produces a subset of the original set (be it a cell or a matrix).

how to multiply a matrix with every cell of cell array in Matlab?

I have a 4D array A size(l,k,s,r) and a cell array B size(i,j) where in each cell a different 4D array of coefficients size(l,k,s,r) is stored.
I want to make changes in the given array C of size(i,j) = C(i,j) + sum(sum(sum(sum(A.*B{i,j})))) without for loop.
in other words I need to extract one by one all arrays out of cell array B and multiply with A.
with the for loop i do it this way:
for i=1:length_of_first_dimension
for j=1:length_of_second_dimension
B_4D=B{i,j}; % extraction of 4D array
dummy(i,j)=sum(sum(sum(sum(B_4D.*A))));
end
end
C=C+dummy;
can anyone help me with that?
first, reshape B into a (length_of_first_dimension*length_of_second_dimension)-by-l*k*s*r 2D matrix
rB = cellfun( #(x) x(:).', B, 'uni', 0 ); %'
rB = vertcat(rB{:});
Now, reshape A into a l*k*s*r-by-1 column vector
rA = A(:);
And simply multiply them
rDummy = rB * rA; %// does the elem-wise product and summation quite quickly.
Reshape the result
dummy = reshape(rDummy, size(B) );
C = C + dummy;
As pointed by Divakar a more efficient way to reshape B would be
rB = reshape( cat( 5, B{:} ), numel(A), [] ).';
And a small benchmark can be found here.

Extract array dimensions in Julia

Given a vector A defined in Matlab by:
A = [ 0
0
1
0
0 ];
we can extract its dimensions using:
size(A);
Apparently, we can achieve the same things in Julia using:
size(A)
Just that in Matlab we are able to extract the dimensions in a vector, by using:
[n, m] = size(A);
irrespective to the fact whether A is one or two-dimensional, while in Julia A, size (A) will return only one dimension if A has only one dimension.
How can I do the same thing as in Matlab in Julia, namely, extracting the dimension of A, if A is a vector, in a vector [n m]. Please, take into account that the dimensions of A might vary, i.e. it could have sometimes 1 and sometimes 2 dimensions.
A = zeros(3,5)
sz = size(A)
returns a tuple (3,5). You can refer to specific elements like sz[1]. Alternatively,
m,n = size(A,1), size(A,2)
This works even if A is a column vector (i.e., one-dimensional), returning a value of 1 for n.
This will achieve what you're expecting:
n, m = size(A); #or
(n, m) = size(A);
If size(A) is a one dimensional Tuple, m will not be assigned, while n will receive length(A). Just be sure to catch that error, otherwise your code may stop if running from a script.

Despite many examples online, I cannot get my MATLAB repmat equivalent working in python

I am trying to do some numpy matrix math because I need to replicate the repmat function from MATLAB. I know there are a thousand examples online, but I cannot seem to get any of them working.
The following is the code I am trying to run:
def getDMap(image, mapSize):
newSize = (float(mapSize[0]) / float(image.shape[1]), float(mapSize[1]) / float(image.shape[0]))
sm = cv.resize(image, (0,0), fx=newSize[0], fy=newSize[1])
for j in range(0, sm.shape[1]):
for i in range(0, sm.shape[0]):
dmap = sm[:,:,:]-np.array([np.tile(sm[j,i,:], (len(sm[0]), len(sm[1]))) for k in xrange(len(sm[2]))])
return dmap
The function getDMap(image, mapSize) expects an OpenCV2 HSV image as its image argument, which is a numpy array with 3 dimensions: [:,:,:]. It also expects a tuple with 2 elements as its imSize argument, of course making sure the function passing the arguments takes into account that in numpy arrays the rows and colums are swapped (not: x, y, but: y, x).
newSize then contains a tuple containing fracions that are used to resize the input image to a specific scale, and sm becomes a resized version of the input image. This all works fine.
This is my goal:
The following line:
np.array([np.tile(sm[i,j,:], (len(sm[0]), len(sm[1]))) for k in xrange(len(sm[2]))]),
should function equivalent to the MATLAB expression:
repmat(sm(j,i,:),[size(sm,1) size(sm,2)]),
This is my problem:
Testing this, an OpenCV2 image with dimensions 800x479x3 is passed as the image argument, and (64, 48) (a tuple) is passed as the imSize argument.
However when testing this, I get the following ValueError:
dmap = sm[:,:,:]-np.array([np.tile(sm[i,j,:], (len(sm[0]),
len(sm[1]))) for k in xrange(len(sm[2]))])
ValueError: operands could not be broadcast together with
shapes (48,64,3) (64,64,192)
So it seems that the array dimensions do not match and numpy has a problem with that. But my question is what? And how do I get this working?
These 2 calculations match:
octave:26> sm=reshape(1:12,2,2,3)
octave:27> x=repmat(sm(1,2,:),[size(sm,1) size(sm,2)])
octave:28> x(:,:,2)
7 7
7 7
In [45]: sm=np.arange(1,13).reshape(2,2,3,order='F')
In [46]: x=np.tile(sm[0,1,:],[sm.shape[0],sm.shape[1],1])
In [47]: x[:,:,1]
Out[47]:
array([[7, 7],
[7, 7]])
This runs:
sm[:,:,:]-np.array([np.tile(sm[0,1,:], (2,2,1)) for k in xrange(3)])
But it produces a (3,2,2,3) array, with replication on the 1st dimension. I don't think you want that k loop.
What's the intent with?
for i in ...:
for j in ...:
data = ...
You'll only get results from the last iteration. Did you want data += ...? If so, this might work (for a (N,M,K) shaped sm)
np.sum(np.array([sm-np.tile(sm[i,j,:], (N,M,1)) for i in xrange(N) for j in xrange(M)]),axis=0)
z = np.array([np.tile(sm[i,j,:], (N,M,1)) for i in xrange(N) for j in xrange(M)]),axis=0)
np.sum(sm - z, axis=0) # let numpy broadcast sm
Actually I don't even need the tile. Let broadcasting do the work:
np.sum(np.array([sm-sm[i,j,:] for i in xrange(N) for j in xrange(M)]),axis=0)
I can get rid of the loops with repeat.
sm1 = sm.reshape(N*M,L) # combine 1st 2 dim to simplify repeat
z1 = np.repeat(sm1, N*M, axis=0).reshape(N*M,N*M,L)
x1 = np.sum(sm1 - z1, axis=0).reshape(N,M,L)
I can also apply broadcasting to the last case
x4 = np.sum(sm1-sm1[:,None,:], 0).reshape(N,M,L)
# = np.sum(sm1[None,:,:]-sm1[:,None,:], 0).reshape(N,M,L)
With sm I have to expand (and sum) 2 dimensions:
x5 = np.sum(np.sum(sm[None,:,None,:,:]-sm[:,None,:,None,:],0),1)
len(sm[0]) and len(sm[1]) are not the sizes of the first and second dimensions of sm. They are the lengths of the first and second row of sm, and should both return the same value. You probably want to replace them with sm.shape[0] and sm.shape[1], which are equivalent to your Matlab code, although I am not sure that it will work as you expect it to.

Resources