Multiply by random number each iteration - matlab

I'd like to multiply a random number vector PT(n)=rand(1,n) by a matrix M(mxn) but want to have a different random vector for each column multiplication. Is it possible in Matlab?
E.g. PT=rand(1,4);
`PT*(1 0 0 0;...
0 0 0 1;...
0 1 0 0;...
0 0 0 1);
but where PT changes for each column multiplication. The only way I can think of is make PT=rand(4,4)and then take diag(PT*M) but it's very expensive if my matrix M is large.
Any thoughts?
Cheers
Suplemental
using #Nasser arrayfun code takes 3 times longer than a for loop. I see it's normal but why the big difference?

I am not sure if I understood exactly what you are asking.
But if you mean you have a matrix of vectors, and you want to multiply another matrix by each one of these vectors then one way is to use arrayfun.
For example: Here we multiply a 5 by 4 matrix with 3 vectors, each is 4 by 1.
The result is 3 vectors, each is 5 by 1
pt = rand(4,3);
M = rand(5,4);
r = arrayfun(#(i) M*pt(:,i),1:size(pt,2),'UniformOutput',false)
gives
r =
[5x1 double] [5x1 double] [5x1 double]
cell2mat(r)
ans =
0.1463 0.4386 0.4638
0.4104 0.8105 0.6455
0.9503 1.0145 1.0369
1.3011 1.4583 1.5233
0.4688 0.7405 0.7492

If I'm following you, how about
M = rand(4,4); % your matrix
PT = rand(4,4); % your random row vectors
rslt = sum(PT'.*M,2); % your desired result

I ma not sure, but according to your example, it looks like you want to do a random permutation of the columns of PT. If that's the case, you can do:
PT=PT(:,randperm(size(PT,2)));

Related

Finding equal rows in Matlab

I have a matrix suppX in Matlab with size GxN and a matrix A with size MxN. I would like your help to construct a matrix Xresponse with size GxM with Xresponse(g,m)=1 if the row A(m,:) is equal to the row suppX(g,:) and zero otherwise.
Let me explain better with an example.
suppX=[1 2 3 4;
5 6 7 8;
9 10 11 12]; %GxN
A=[1 2 3 4;
1 2 3 4;
9 10 11 12;
1 2 3 4]; %MxN
Xresponse=[1 1 0 1;
0 0 0 0;
0 0 1 0]; %GxM
I have written a code that does what I want.
Xresponsemy=zeros(size(suppX,1), size(A,1));
for x=1:size(suppX,1)
Xresponsemy(x,:)=ismember(A, suppX(x,:), 'rows').';
end
My code uses a loop. I would like to avoid this because in my real case this piece of code is part of another big loop. Do you have suggestions without looping?
One way to do this would be to treat each matrix as vectors in N dimensional space and you can find the L2 norm (or the Euclidean distance) of each vector. After, check if the distance is 0. If it is, then you have a match. Specifically, you can create a matrix such that element (i,j) in this matrix calculates the distance between row i in one matrix to row j in the other matrix.
You can treat your problem by modifying the distance matrix that results from this problem such that 1 means the two vectors completely similar and 0 otherwise.
This post should be of interest: Efficiently compute pairwise squared Euclidean distance in Matlab.
I would specifically look at the answer by Shai Bagon that uses matrix multiplication and broadcasting. You would then modify it so that you find distances that would be equal to 0:
nA = sum(A.^2, 2); % norm of A's elements
nB = sum(suppX.^2, 2); % norm of B's elements
Xresponse = bsxfun(#plus, nB, nA.') - 2 * suppX * A.';
Xresponse = Xresponse == 0;
We get:
Xresponse =
3×4 logical array
1 1 0 1
0 0 0 0
0 0 1 0
Note on floating-point efficiency
Because you are using ismember in your implementation, it's implicit to me that you expect all values to be integer. In this case, you can very much compare directly with the zero distance without loss of accuracy. If you intend to move to floating-point, you should always compare with some small threshold instead of 0, like Xresponse = Xresponse <= 1e-10; or something to that effect. I don't believe that is needed for your scenario.
Here's an alternative to #rayryeng's answer: reduce each row of the two matrices to a unique identifier using the third output of unique with the 'rows' input flag, and then compare the identifiers with singleton expansion (broadcast) using bsxfun:
[~, ~, w] = unique([A; suppX], 'rows');
Xresponse = bsxfun(#eq, w(1:size(A,1)).', w(size(A,1)+1:end));

Assigning values to a matrix through vector addition from an adjacency matrix

Very new to Matlab, I usually use STATA.
I want to use the nchoosek fuction to get the sum of vectors in one matrix.
I have a 21x21 adjacency matrix, with either 0 or 1 as the inputs. I want to create a new matrix, that will give me a sum of inputs between all possible triads from the adjacency matrix.
The new matrix should look have four variables, indexes (i, j, k) - corresponding to each combination from the 21x21. And a final variable which is a sum of the inputs.
The code I have so far is:
C = nchoosek(21,3)
B = zeros(nchoosek(21,3), 4)
for i=1:C
for j=i+1:C
for k=j+1:C
B(?)=B(i, j, k, A(i)+A(j)+A(k)) #A is the 21x21 adj mat
end
end
end
I know my assignment statement is incorrect as I don't completed understand the indexing role of the ":" operator. Any help will be appreciated.
Thanks!
This might be what you want:
clear all
close all
clc
A = rand(21,21); % Replace this with actual A
rowNum = 0;
for i=1:21
for j=i+1:21
for k=j+1:21
rowNum = rowNum+1;
B(rowNum,:) = [i, j, k, sum(A(:,i)+A(:,j)+A(:,k))];
end
end
end
There are some points:
You loop for different combinations. the total number of combination is nchoosek(21,3) which you can check after 3 nested loop. Your code with for i=1:C was the first error since you're actually looping for different values of i and different values of j and k. So these just 21 values not more.
To avoid repeated combinations, it's enough to start new index after the previous one, which you've realized in your code.
There are other possible approaches such as vectorized format, but to stick to your approach, I used a counter: rowNum which is the loop counter and updated along the loop.
B(rowNum,:) means all element of rowNum'th row of the matrix B.
Below is an algorithm to find the triads in an adjacency matrix. It checks all possible triads and sums the values.
%basic adjacency matrix with two triads (1-2-5) (2-3-5)
A=[];
A(1,:) = [0 1 0 0 1];
A(2,:) = [1 0 1 0 1];
A(3,:) = [0 1 0 0 1];
A(4,:) = [0 0 0 0 1];
A(5,:) = [1 1 1 1 0];
A=A==1; %logical matrix
triads=nchoosek(1:5,3);
S=nan(size(triads,1),4);
for ct = 1:size(triads,1)
S(ct,1:3)=[A(triads(ct,1),triads(ct,2)),A(triads(ct,1),triads(ct,3)),A(triads(ct,2),triads(ct,3))];
S(ct,4)=sum(S(ct,1:3));
end
triads(find(S(:,4)==3),:)
ans =
1 2 5
2 3 5

assign new matrix values based on row and column index vectors

New to MatLab here (R2015a, Mac OS 10.10.5), and hoping to find a solution to this indexing problem.
I want to change the values of a large 2D matrix, based on one vector of row indices and one of column indices. For a very simple example, if I have a 3 x 2 matrix of zeros:
A = zeros(3, 2)
0 0
0 0
0 0
I want to change A(1, 1) = 1, and A(2, 2) = 1, and A(3, 1) = 1, such that A is now
1 0
0 1
1 0
And I want to do this using vectors to indicate the row and column indices:
rows = [1 2 3];
cols = [1 2 1];
Is there a way to do this without looping? Remember, this is a toy example that needs to work on a very large 2D matrix. For extra credit, can I also include a vector that indicates which value to insert, instead of fixing it at 1?
My looping approach is easy, but slow:
for i = 1:length(rows)
A(rows(i), cols(i)) = 1;
end
sub2ind can help here,
A = zeros(3,2)
rows = [1 2 3];
cols = [1 2 1];
A(sub2ind(size(A),rows,cols))=1
A =
1 0
0 1
1 0
with a vector to 'insert'
b = [1,2,3];
A(sub2ind(size(A),rows,cols))=b
A =
1 0
0 2
3 0
I found this answer online when checking on the speed of sub2ind.
idx = rows + (cols - 1) * size(A, 1);
therefore
A(idx) = 1 % or b
5 tests on a big matrix (~ 5 second operations) shows it's 20% faster than sub2ind.
There is code for an n-dimensional problem here too.
What you have is basically a sparse definition of a matrix. Thus, an alternative to sub2ind is sparse. It will create a sparse matrix, use full to convert it to a full matrix.
A=full(sparse(rows,cols,1,3,2))

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,:))

Matlab:Efficient assignment of values in a sparse matrix

I'm working in Matlab and I have the next problem:
I have a B matrix of nx2 elements, which contains indexes for the assignment of a big sparse matrix A (almost 500,000x80,000). For each row of B, the first column is the column index of A that has to contain a 1, and the second column is the column index of A that has to contain -1.
For example:
B= 1 3
2 5
1 5
4 1
5 2
For this B matrix, The Corresponding A matrix has to be like this:
A= 1 0 -1 0 0
0 1 0 0 -1
1 0 0 0 -1
-1 0 0 1 0
0 -1 0 0 1
So, for the row i of B, the corresponding row i of A must be full of zeros except on A(i,B(i,1))=1 and A(i,B(i,2))=-1
This is very easy with a for loop over all the rows of B, but it's extremely slow. I also tried the next formulation:
A(:,B(:,1))=1
A(:,B(:,2))=-1
But matlab gave me an "Out of Memory Error". If anybody knows a more efficient way to achieve this, please let me know.
Thanks in advance!
You can use the sparse function:
m = size(B,1); %// number of rows of A. Or choose larger if needed
n = max(B(:)); %// number of columns of A. Or choose larger if needed
s = size(B,1);
A = sparse(1:s, B(:,1), 1, m, n) + sparse(1:s, B(:,2), -1, m, n);
I think you should be able to do this using the sub2ind function. This function converts matrix subscripts to linear indices. You should be able to do it like so:
pind = sub2ind(size(A),1:n,B(:,1)); % positive indices
nind = sub2ind(size(A),1:n,B(:,2)); % negative indices
A(pind) = 1;
A(nind) = -1;
EDIT: I (wrongly, I think) assumed the sparse matrix A already existed. If it doesn't exist, then this method wouldn't be the best option.