How to add vectors of different length in MATLAB - matlab

I'm trying to do the following:
Let's say I have:
x1=[7];
x2=[3 4];
x3=[1 -1 5];
x4=[2 5 -1 3];
and I want to add them together.
I know it's not possible to add vectors of different dimensions, but what I'm trying to achieve is a new vector having:
v=[2 5+1 -1-1+3 3+5+4+7];
I tried to pad the relevant vectors with zeros, to get:
x1=[0 0 0 7];
x2=[0 0 3 4];
x3=[0 1 -1 5];
x4=[2 5 -1 3];
and then the addition will be natural, but couldn't find a way to do it.
Of course, I'm looking for an iterative method of doing that, meaning, every vector xi is the result of the i'th iteration, where the number of iterations, n, is known in advance. (in the above example n=4)

My first thought would be something like
x1 = [zeros(1, 4 - length(x1)) x1];
Where you would substitute max(all_your_arrays) for 4 in the above line. If your arrays are in cell arrays you should be able to easily adapt that to a loop.

Related

Using vector as indices not working as expected, matlab

Given a nXm matrix A and a mX2 matrix B and a matrix C of size mX1 containing 1s and 2s C=[1 2 1 2 1...], depending on which column, I want every row of A to be multiplied with. How can this be done? Or equivalently, given D = A*B how can I access only the values dictated by C. I tried D(:,C), but the result is not the expected.
Example a =[1 2; 3 4; 5 6] . c = [1 2 1] . a(?) = [1 4 5]
Any idea?
%example data
n=10;m=20;
A=rand(n,m)
B=rand(m,2)
C=round(rand(m,1))+1;
%solution:
B2=B(:,1); %multiplication vector
B2(C==2)=B(C==2,2) %change the ones where C==2
A*B2
You can run the following command for the last example:
a(sub2ind([3,2],1:3,c))'
In general case you can do like the following:
% n is the length of the D which is nx2 matrix
D(sub2ind([n,2],1:n,C))'

matlab: sum of f(k_i,x) where k_i are scalars and x is a matrix

Any idea how to formulate this sum other than using a loop?
sum(i) f(k(i),x) where k_i are some entries of a vector and x is a matrix.
Currently what I'm doing is this, but I'd rather have a general solution:
for ii=1:length(k)
psi=psi+f(k(ii),x)
end
If it's any concern:
f(k,x)=g(k)*exp(k*x)
Assuming g can take a vector input and returns a vector result of the same size, and that x is just a scalar
f=#(k,x) g(k).*exp(k*x);
psi=sum(f(k,x))
or if g can't be or isn't able to take vector input, you can do
g=#(k) arrayfun(g,k);
and then define f as before.
Do you mean that you want to sum only specific rows?
If so, this will do it:
a= [1 2 3 4;
5 2 7 2;
0 0 2 3];
k= [1 3]; %rows selection for sum
result= sum(a(k,:))

How does "/" really work on two row vectors?

I have the following basic observation:
[1 2 3 4]/[2 4 6 8] % output: 0.5
[1 2 3 4]/[2 3 4 5] % output: 0.7407
([1 2 3 4]*[2 4 6 8] % error of course)
It does not look for me as A*inv(B) kind of operation (nor like mrdivide on timeseries which would work like [1 2 3 4]./[2 4 6 8] if Im not mistaken).
Now, my question is, what operation does "/" define on two row vectors with the same length?
UPDATE:
#user1884905 gave the idea that a/b on two row vectors might minimise norm(b*x - a). So far it seemed to work on some numeric tests. If it is true, can you give some official reference behind this please?
Yes, it seems I was right. From MathWorks mrdivide
"If A is a rectangular m-by-n matrix with m ~= n, and B is a row vector with n elements or a matrix with n columns, then x = B/A returns a least-squares solution of the system of equations x*A = B."

find the nearest point pairs between two sets of of matrix

Assume I have two sets of matrix (A and B), inside each matrix contains few point coordinates, I want to find out point in B nearest to A and output a cell array C listed the nearest point pair coordinates accordingly and one cell array D register the unpaired spot, how should I do it?
To be more specific, here is what I want
Two sets of matrix contain spot xy coordinates;
A=[ 1 2; 3 4]; B=[1 3; 5 6; 2 1];
want to get C{1,1}=[1 2; 1 3]; C{2,1}= [3 4; 5 6]; D{1,1}=[2 1];
Thanks for the help.
There is not exactly one solution to this problem, take for example the (one-dimensional, but expandable to N-D) case:
A= [1; 3];
B= [2];
Then either A(1) or A(2) can be the leftover point. Which one your algorithm spits out, will depend on how it works, ie which point you take first to find the nearest point.
Such algorithm consists imo of
Finding distances between each combination of A(i) and B(j). If you have the statistics toolbox, pdist2 does this for you:
A=[ 1 2; 3 4];
B=[1 3; 5 6; 2 1];
dist = pdist2(A,B);
Looping over the smallest of A or B (I'll take A, cause it is smallest in your example) and finding for each point in A the closest point in the remaining set of B:
N = size(A,1);
matchAtoB=NaN(N,1);
for ii=1:N
dist(:,matchAtoB(1:ii-1))=Inf; % make sure that already picked points of B are not eligible to be new closest point
[~,matchAtoB(ii)]=min(dist(ii,:));
end
matchBtoA = NaN(size(B,1),1);
matchBtoA(matchAtoB)=1:N;
remaining_indices = find(isnan(matchBtoA));
Combine result to your desired output matrices C and D:
C=arrayfun(#(ii) [A(ii,:) ; B(matchAtoB(ii),:)],1:N,'uni',false);
D=mat2cell(B(remaining_indices,:),ones(numel(remaining_indices),1),size(B,2));
Note that this code will also work with 1D points or higher (N-D), the pdist2 flattens everything out to scalar distances.
Here's my take on the problem:
A=[1 2
3 4];
B=[1 3
5 6
2 1];
dists = pdist2(A,B);
[dists, I] = sort(dists,2);
c = NaN(size(A,1),1);
for ii = 1:size(A,1)
newC = find(~any(bsxfun(#eq, I(ii,:), c), 1));
c(ii) = I(ii,newC(1));
end
C = cellfun(#(x)reshape(x,2,2).',...
mat2cell([A B(c,:)], ones(size(A,1),1), 4), 'uni', false);
D = {B(setdiff(1:size(B,1),c), :)}
This solution assumes
all your vectors are 2D
stacked in rows of A and B
and A is always the source (i.e., everything is compared to A)
If these assumptions do not (always) hold, you'll have to take a more general approach, like the one suggested by #GuntherStruyf.

What is the quickest way to keep the non dominated elements and omit the rest in MATLAB?

For example [2 , 5] dominates [3 , 8] cause (2 < 3) and (5 < 8)
but [2 , 5] does not dominates [3 , 1] cause though (2 < 3) but (5 > 1) so these two vectors are non dominated
now for example assume that I have a matrix like this :
a =[ 1 8;
2 6;
3 5;
4 6];
here the first three are non dominated but the last one is dominated by (3,5), I need a code which can omit it and give me this output:
ans =
[ 1 8;
2 6;
3 5]
note that there may be lots of non dominated elements in a Nx2 matrix
Compare one row with other rows using bsxfun
Do this for every row using arrayfun (or a loop if you prefer that) and transform the output back to a matrix with cell2mat
use any and all to check which rows are dominated
remove these rows
code:
a=[1 8;2 6;3 5;4 6];
dominated_idxs = any(cell2mat(arrayfun(#(ii) all(bsxfun(#(x,y) x>y,a,a(ii,:)),2),1:size(a,1),'uni',false)),2);
a(dominated_idxs,:) = [];
edit
If you want to use >= instead of > comparison, each row will dominate itself and will be removed, so you'll end up with an empty matrix. Filter these false-positives out by adjusting the code as follows:
a=[1 8;2 6;3 5;4 6];
N = size(a,1);
compare_matrix = cell2mat(arrayfun(#(ii) all(bsxfun(#(x,y) x>=y,a,a(ii,:)),2),1:N,'uni',false));
compare_matrix(1:N+1:N^2)=false; % set diagonal to false
dominated_idxs = any(compare_matrix,2);
a(dominated_idxs ,:) = [];
This problem is identical to identifying the so-called Pareto front.
If the number of elements N grows large and/or you need to carry out this sort of operation often (as I suspect you do), you might want to give a thought to a fully optimized MEX file for this purpose (available on the Mathworks File Exchange):
Compiling this, putting the mex in your Matlab path, and then using something like
a = a(paretofront(a));
will accomplish your task much quicker than any combination of Matlab-builtins is able to.