Suppose I have vectors z1 z2 z3 z4 and b and matrices D1 D2 D3 D4.
I want to construct:
b1 = D2*z2 + D3*z3 +D4*z4 -b
b2 = D1*z1 + D3*z3 +D4*z4 -b
b3 = D1*z1 + D2*z2 +D4*z4 -b
b4 = D1*z1 + D2*z2 +D3*z3 -b
I planned to store my z vectors and D matrices in cells and extract them to create b by a for loop. e.g.
for i = 1:3
b(i) = D{i+1}*z{i+1} + D{i}*z{i};
end
Of course it certainly fails because it involves D{i}*z{i} at each i step. Can you please help me to accomplish my task?
You can do it like this (no recursion, but still any pair-wise product is only computed once).
pairs = zeros(size(D{1},1), 4);
for ii=4:-1:1,
pairs(:,ii) = D{ii}*z{ii};
end
Once you have the product of all pairs, you can take the sum
all_sum = sum(pairs, 2) - b_vec; % D1*z1 + D2*z2 + D3*z3 +D4*z4 -b
To get the proper b_i you only need to subtract pairs(:,ii) from the sum:
for ii=4:-1:1
b{ii} = all_sum - pairs{ii};
end
Related
I'm running a Matlab code in the HPC of my university. I have two versions of the code. The second version, despite generating a smaller array, seems to require more memory. I would like your help to understand if this is in fact the case and why.
Let me start from some preliminary lines:
clear
rng default
%Some useful components
n=7^4;
vectors{1}=[1,20,20,20,-1,Inf,-Inf];
vectors{2}=[-19,19,19,19,-20,Inf,-Inf];
vectors{3}=[-19,0,0,0,-20,Inf,-Inf];
vectors{4}=[-19,0,0,0,-20,Inf,-Inf];
T_temp = cell(1,4);
[T_temp{:}] = ndgrid(vectors{:});
T_temp = cat(4+1, T_temp{:});
T = reshape(T_temp,[],4); %all the possible 4-tuples from vectors{1}, ..., vectors{4}
This is the first version 1 of the code: I construct the matrix D1 listing all possible pairs of unordered rows from T
indices_pairs=pairIndices(n);
D1=[T(indices_pairs(:,1),:) T(indices_pairs(:,2),:)];
This is the second version of the code: I construct the matrix D2 listing a random draw of m=10^6 unordered pairs of rows from T
m=10^6;
p=n*(n-1)/2;
random_indices_pairs = randperm(p, m).';
[C1, C2] = myind2ind (random_indices_pairs, n);
indices_pairs=[C1 C2];
D2=[T(indices_pairs(:,1),:) T(indices_pairs(:,2),:)];
My question: when generating D2 the HPC goes out of memory. When generating D1 the HPC works fine, despite D1 being a larger array than D2. Why is that the case?
These are complementary functions used above:
function indices = pairIndices(n)
[y, x] = find(tril(logical(ones(n)), -1)); %#ok<LOGL>
indices = [x, y];
end
function [R , C] = myind2ind(ii, N)
jj = N * (N - 1) / 2 + 1 - ii;
r = (1 + sqrt(8 * jj)) / 2;
R = N -floor(r);
idx_first = (floor(r + 1) .* floor(r)) / 2;
C = idx_first-jj + R + 1;
end
Suppose I have a row matrix [a1 a2 a3 a4 .. an] and I wish to achieve each of the following in MATLAB
1) 1+a1
2) 1+a1+a2
3) 1+a1+a2+a3
4) 1+a1+a2+a3+a4
....
1+a1+a2+...+an
How shall I get them?
This is the purpose of the cumsum function. If A is a vector containing the elements [a1 a2 a3 .. an] then
B = cumsum([1 A]);
contains the terms you are searching for. Another possibility is
B = 1 + cumsum(A);
Edit
If you don't want to use a built-in function like cumsum, then the simpler way to go is to do a for loop:
% Consider preallocation for speed
B = NaN(numel(A),1);
% Assign the first element
B(1) = 1 + A(1);
% The loop
for i = 2:numel(A)
B(i) = B(i-1) + A(i);
end
or, without preallocation:
B = 1 + A(1);
for i = 2:numel(A)
B(end+1) = B(end) + A(i);
end
Best,
I would like to seek y particular of ODE y'' - y' - 2y = 4x^2
I made the following script:
syms x A0 A1 A2
ypa = A2*x^2+A1*x+A0; % y_p assume
cyp = diff(ypa,2) - diff(ypa) - 2*ypa % according to ODE
P1 = 4*x^2; P2 = cyp ; % Equating P1 and P2
C = coeffs(P1 - P2,x);
A0 = solve(C(1),A0)
A1 = solve(C(2),A1)
A2 = solve(C(3),A2)
I got the correct answer for A2 = -2. But I did not get for A0 (should be -3) and A1 (should be 2). How to get them automatically?
P.S I'm using MATLAB R2013a.
Instead of calling solve 3 times, once on each equation of C, you should call it once on the entire system of equations so that the proper substitutions are done to give you a numeric result for each variable:
>> [A0, A1, A2] = solve(C)
A0 =
-3
A1 =
2
A2 =
-2
I need to do function that works like this :
N1 = size(X,1);
N2 = size(Xtrain,1);
Dist = zeros(N1,N2);
for i=1:N1
for j=1:N2
Dist(i,j)=D-sum(X(i,:)==Xtrain(j,:));
end
end
(X and Xtrain are sparse logical matrixes)
It works fine and passes the tests, but I believe it's not very optimal and well-written solution.
How can I improve that function using some built Matlab functions? I'm absolutely new to Matlab, so I don't know if there really is an opportunity to make it better somehow.
You wanted to learn about vectorization, here some code to study comparing different implementations of this pair-wise distance.
First we build two binary matrices as input (where each row is an instance):
m = 5;
n = 4;
p = 3;
A = double(rand(m,p) > 0.5);
B = double(rand(n,p) > 0.5);
1. double-loop over each pair of instances
D0 = zeros(m,n);
for i=1:m
for j=1:n
D0(i,j) = sum(A(i,:) ~= B(j,:)) / p;
end
end
2. PDIST2
D1 = pdist2(A, B, 'hamming');
3. single-loop over each instance against all other instances
D2 = zeros(m,n);
for i=1:n
D2(:,i) = sum(bsxfun(#ne, A, B(i,:)), 2) ./ p;
end
4. vectorized with grid indexing, all against all
D3 = zeros(m,n);
[x,y] = ndgrid(1:m,1:n);
D3(:) = sum(A(x(:),:) ~= B(y(:),:), 2) ./ p;
5. vectorized in third dimension, all against all
D4 = sum(bsxfun(#ne, A, reshape(B.',[1 p n])), 2) ./ p;
D4 = permute(D4, [1 3 2]);
Finally we compare all methods are equal
assert(isequal(D0,D1,D2,D3,D4))
In MATLAB I have a matrix with of 80000*20 numbers. I would like to calculate the mean, maximum and minumum for the first 100 numbers in column 1 (0-100), the next (second) 100 numbers (101-200) in column 1, the third 100 numbers in column 1 (201-300), etc. Simular for all columns. I think I need sort of a loop to separate the matrix, because of the large deminsions of the matrix. How can I do this?
So for example:
Matrix:
A1 A2 A3 A4 A5
B1 B2 B3 B4 B5
C1 C2 C3 C4 C5
D1 D2 D3 D4 D5
E1 E2 E3 E4 E5
F1 F2 F3 F4 F5
Then I would like the mean, minumun and maximum of A1 B1 C1 and mean, minimum and maximum of D1 E1 F1. Simular for column 2 (A2 B2 C2) and (D2 E2 F2),3,4,5,6..etc
regards,
Vincent
Here is an example of two possible solutions. One uses a loop. The other converts your matrix into a cell array, performs the operations on the cell array using cellfun, and then converts the answer back to a matrix.
%# Build random matrix X
T = 12;
N = 3;
X = randi(100, T, N);
%# Set the number of elements in each mean, min, and max calculation
K = 4;
%# Determine the number of groups
L = T / K;
if mod(L, 1) ~= 0; error('Number of rows not integer divisible by number of elements per group'); end
%# Loop based solution
Soln1 = nan(L, N);
for k = 1:K-1
Soln1(k, :) = mean(X(k * K - K + 1:k * K, :));
end
%# Loop-less solution
CellOfMat = mat2cell(X, K * ones(L, 1), N);
Soln2 = cellfun(#mean, CellOfMat, 'UniformOutput', 0);
Soln2 = cell2mat(Soln2);
I have done the solution for the mean function in the above example. The case of max and min follows trivially upon substitution of those functions.
Here's an alternative loop-less solution that doesn't use cells.
% M is the 80000x20 matrix
rows_per_dataset = 100;
rows_in_solution = size(M,1)/rows_per_dataset;
% flatten out the matrix so each column is one dataset
M_grouped = reshape(M,rows_per_dataset,rows_in_solution*size(M,2));
means = mean(M_grouped);
means = reshape(means,rows_in_solution,size(M,2));
% the value in each row and column is the mean of the corresponding dataset
% in the original data
For large enough data sets, however, copying the data to a temporary variable is inefficient, and a loop-based solution is better.