Sum each n elements and store in another vector matlab - matlab

I have the following function:
b = [-1 1];
m = b(randi(length(b),1,nsimul*n));
Is there a way to do sum to every n elements and store in another vector?
Example:
b = [-1 1];
m = b(randi(length(b),1,5*2));
m
m =
1 -1 1 -1 1 -1 -1 1 1 -1
A(1) = m(1) + m(2);
A(2) = m(3) + m(4);
A(3) = m(5) + m(6);
A(4) = m(7) + m(8);
A(5) = m(9) + m(10);
A
A =
0 0 0 0 0

you can use vec2mat to reshape you vector to a matrix of the dimension that fits the # of elements you want to sum on, and the you just need to sum the right dimension.
vec2mat is nice because it will pad with zeros the reminder of the 1D vector in case you choose a # of elements that is incommensurate with a NxM matrix, For example:
vec2mat(m,2)
ans =
1 -1
1 -1
1 -1
-1 1
1 -1
more generally, let's call n_elements the # of elements you want to sum on, then:
n_elements=2;
a=sum(vec2mat(m,n_elements),2)
But if the 1D vector and the # of elements is always commensurate and no padding is needed you can use the good old reshape, as mentioned in the comments below...

The following code snippet should provide what you are looking for:
% Define the parameters...
nsimul = 5;
n = 2;
b = [-1 1];
% Compute the final result...
m = b(randi(length(b),1,nsimul*n));
k = sum(reshape(m,n,[]).',2);
Given, for example, the vector:
m = [-1 -1 1 1 -1 -1 -1 1 1 1]
The final result s would be:
s = [-2 2 -2 0 2]
with the intermediate result k given by the reshape function equal to:
k = [
-1 -1
1 1
-1 -1
-1 1
1 1
]

Related

Split vector to multiple vectors

I'm looking for a simple method to transforming a vector of the following type
[1 1 0 1 1]
To this group of vectors:
[0 0 0 0 1]
[0 0 0 1 0]
[0 1 0 0 0]
[1 0 0 0 0]
The vector itself represents polynomial coefficients (x^4 + x^3 + x + 1)
Thanks
Here are some approaches. Input is a vector v, output is a matrix M:
[~, rr, vv] = find(v);
M = full(sparse(1:nnz(v), flip(rr), 1));
M = flip(eye(numel(v)));
M = M(logical(v),:)
M = zeros(nnz(v), numel(v));
M(sub2ind(size(M), 1:size(M,1), flip(find(v)))) = 1;
M = double(bsxfun(#eq, flip(find(v(:))), 1:numel(v)));

Quick Assembly of sparse matrix

I have indices
I = [nGrid x 9] matrix % mesh on fine grid (9 point rectangle)
J = [nGrid x 4] matrix % mesh on coarse grid (4 point rectangle)
Here, nGrid is large number depending on the mesh (e.g. 1.e05)
Then I want to do like
R_ref = [4 x 9] matrix % reference restriction matrix from fine to coarse
P_ref = [9 x 4] matrix % reference prolongation matrix from coarse to fine
R = sparse(size) % n_Coarse x n_Fine
P = sparse(size) % n_Fine x n_Coarse
for k = 1 : nGrid % number of elements on coarse grid
R(I(k,:),J(k,:)) = R_ref;
P(J(k,:),I(k,:)) = P_ref;
end
size is predetermined number.
Note that even if there is same index in (I,J), I do not want to accumulate. I just want to put stencils Rref and Pref at each indices respectively.
I know that this is very slow due to the data structure of sparse.
Usually, I use
sparse(row,col,entry,n_row,n_col)
I can use this by manipulate I, J, R_ref, P_ref by bsxfun and repmat.
However, this cannot be done because of the accumulation of sparse function
(if there exists (i,j) such that [row(i),col(i)]==[row(j),col(j)], then R(row(i),row(j)) = entry(i)+entry(j))
Is there any suggestion for this kind of assembly procedure?
Sample code
%% INPUTS
% N and M could be much larger
N = 2^5+1; % number of fine grid in x direction
M = 2^5+1; % number of fine grid in y direction
% [nOx * nOy] == nGrid
nOx = floor((M)/2)+1; % number of coarse grid on x direction
nOy = floor((N)/2)+1; % number of coarse grid on y direction
Rref = [4 4 -1 4 -2 0 -1 0 0
-1 -1 -2 4 4 4 -1 4 4
-1 -1 4 -2 4 -2 4 4 -1
0 4 4 0 0 4 -1 -2 -1]/8;
Pref = [2 1 0 1 0 0 0 0 0
0 0 0 1 1 1 0 1 2
0 0 1 0 1 0 2 1 0
0 2 1 0 0 1 0 0 0]'/2;
%% INDEX GENERATION
tri_ref = reshape(bsxfun(#plus,[0,1,2]',[0,N,2*N]),[],1)';
TRI_ref = reshape(bsxfun(#plus,[0,1]',[0,nOy]),[],1)';
I = reshape(bsxfun(#plus,(1:2:N-2)',0:2*N:(M-2)*N),[],1);
J = reshape(bsxfun(#plus,(1:nOy-1)',0:nOy:(nOx-2)*nOy),[],1);
I = bsxfun(#plus,I,tri_ref);
J = bsxfun(#plus,J,TRI_ref);
%% THIS PART IS WHAT I WANT TO CHANGE
R = sparse(nOx*nOy,N*M);
P = R';
for k = 1 : size(I,1)
R(J(k,:),I(k,:)) = Rref;
P(I(k,:),J(k,:)) = Pref;
end

Fastest way of generating a logical matrix by given row indices of true values?

What is the most efficient way of generating
>> A
A =
0 1 1
1 1 0
1 0 1
0 0 0
with
>> B = [2 3; 1 2; 1 3]
B =
2 3
1 2
1 3
in MATLAB?
E.g., B(1, :), which is [2 3], means that A(2, 1) and A(3, 1) are true.
My attempt still requires one for loop, iterating through B's row. Is there a loop-free or more efficient way of doing this?
This is one way of many, though sub2ind is the dedicated function for that:
%// given row indices
B = [2 3; 1 2; 1 3]
%// size of row index matrix
[n,m] = size(B)
%// size of output matrix
[N,M] = deal( max(B(:)), n)
%// preallocation of output matrix
A = zeros(N,M)
%// get col indices to given row indices
cols = bsxfun(#times, ones(n,m),(1:n).')
%// set values
A( sub2ind([N,M],B,cols) ) = 1
A =
0 1 1
1 1 0
1 0 1
If you want a logical matrix, change the following to lines
A = false(N,M)
A( sub2ind([N,M],B,cols) ) = true
Alternative solution
%// given row indices
B = [2 3; 1 2; 1 3];
%// number if rows
r = 4; %// e.g. = max(B(:))
%// number if cols
c = 3; %// size(B,1)
%// preallocation of output matrix
A = zeros(r,c);
%// set values
A( bsxfun(#plus, B.', 0:r:(r*(c-1))) ) = 1;
Here's a way, using the sparse function:
A = full(sparse(cumsum(ones(size(B))), B, 1));
This gives
A =
0 1 1
1 1 0
1 0 1
If you need a predefined number of rows in the output, say r (in your example r = 4):
A = full(sparse(cumsum(ones(size(B))), B, 1, 4, size(B,1)));
which gives
A =
0 1 1
1 1 0
1 0 1
0 0 0
You can equivalently use the accumarrray function:
A = accumarray([repmat((1:size(B,1)).',size(B,2),1), B(:)], 1);
gives
A =
0 1 1
1 1 0
1 0 1
Or with a predefined number of rows, r = 4,
A = accumarray([repmat((1:size(B,1)).',size(B,2),1), B(:)], 1, [r size(B,1)]);
gives
A =
0 1 1
1 1 0
1 0 1
0 0 0

How to formulate this expression

I am new to MATLAB and I want to formulate the following lease square expression in Matlab. I have some codes that I am typing here. But the optimization problem solution seems not to be correct. Does anyone has an idea why?
First, I want to solve the heat equation
$$T_t(x,t) = - L_x . T(x,t) + F(x,t)$$
where L_x is Laplacian matrix of the graph.
then find y from the following least square.
$$ \min_y \sum_{j} \sum_{i} (\hat{T}_j(t_i) - T_j(t_i, y))^2$$
Thanks in advance!!
Here is my code:
%++++++++++++++++ main ++++++++++++++++++++
% incidence matrix for original graph
C_hat = [ 1 -1 0 0 0 0;...
0 1 -1 0 0 -1;...
0 0 0 0 -1 1;...
0 0 0 1 1 0;...
-1 0 1 -1 0 0];
% initial temperature for each vertex in original graph
T_hat_0 = [0 7 1 9 4];
[M_bar,n,m_bar,T_hat_heat,T_hat_temp] = simulate_temp(T_hat_0,C_hat);
C = [ 1 1 -1 -1 0 0 0 0 0 0;...
0 -1 0 0 1 -1 1 0 0 0;...
0 0 1 0 0 1 0 -1 -1 0;...
0 0 0 1 0 0 -1 0 1 -1;...
-1 0 0 0 -1 0 0 1 0 1];
%
% initial temperature for each vertex in original graph
T_0 = [0 7 1 9 4];
%
% initial temperature simulation
[l,n,m,T_heat,T_temp] = simulate_temp(T_0,C);
%
% bounds for variables
lb = zeros(m,1);
ub = ones(m,1);
%
% initial edge weights
w0 = ones(m,1);
% optimization problem
% w = fmincon(#fun, w0, [], [], [], [], lb, ub);
%++++++++++++++++++++ function++++++++++++++++++++++++++++
function [i,n,m,T_heat,T_temp] = simulate_temp(T,C)
%
% initial conditions
delta_t = 0.1;
M = 20; %% number of time steps
t = 1;
[n,m] = size(C);
I = eye(n);
L_w = C * C';
T_ini = T';
Temp = zeros(n,1);
% Computing Temperature
%
for i=1:M
K = 2*I + L_w * delta_t;
H = 2*I - L_w * delta_t;
%
if i == 1
T_heat = (K \ H) * T_ini;
%
t = t + delta_t;
else
T_heat = (K \ H) * Temp;
%
t = t + delta_t;
end
% replacing column of T_final with each node temperature in each
% iteration. It adds one column to the matrix in each step
T_temp(:,i) = T_heat;
%
Temp = T_heat;
end
end
%++++++++++++++++++ function+++++++++++++++++++++++++++++++++++++++++
function w_i = fun(w);
%
for r=1:n
for s=1:M_bar
w_i = (T_hat_temp(r,s) - T_temp(r,s)).^2;
end
end
To give a more clear answer, I need more information about what form you have the functions F_j and E_j in.
I've assumed that you feed each F_j a value, x_i, and get back a number. I've also assumed that you feed E_j a value x_i, and another value (or vector) y, and get back a value.
I've also assumed that by 'i' and 'j' you mean the indices of the columns and rows respectively, and that they're finite.
All I can suggest without knowing more info is to do this:
Pre-calculate the values of the functions F_j for each x_i, to give a matrix F - where element F(i,j) gives you the value F_j(x_i).
Do the same thing for E_j, giving a matrix E - where E(i,j) corresponds to E_j(x_i,y).
Perform (F-E).^2 to subtract each element of F and E, then square them element-wise.
Take sum( (F-E).^2**, 2)**. sum(M,2) will sum across index i of matrix M, returning a column vector.
Finally, take sum( sum( (F-E).^2, 2), 1) to sum across index j, the columns, this will finally give you a scalar.

Want to Create A Combination of Non-Decreasing Elements with Condition

I want to create a combination of non-decreasing elements. The combination will be like,
If i=10 and w=5, then the elements of the combination can be any value from 1 to w and the sum will be equal to i.
Possible combinations are like,
1+1+1+1+1+5
1+1+1+1+1+1+4
1+1+1+1+1+1+1+3
1+1+1+1+1+1+1+1+1+1
......
But 1+1+1+7 is not a desired combination because 7 is greater than w
How to get the combinations using MatLab? I need to get the combinations for higher values of i and w like may be i=20 and w=8.
Thank You
You can do it with a recursive function. The following code contains a wrapper function and the recursive function which does the actual work:
function result = partitions(s,M)
%// s: desired sum; M: maximum value
result = partitions_rec(s,1,M,s);
end
function mat = partitions_rec(s,m,M,n)
%// s: desired sum, m: minimum value; M: maximum value; n: number of entries
M = min(M,s);
if s==0
mat = zeros(1,n);
else
mat = [];
for ii = m:M;
aux = partitions_rec(s-ii,ii,M,n-1);
if size(aux,1)
mat = [ mat; ii*ones(size(aux,1),1) aux ];
end
end
end
end
Example:
>> result = partitions(5,3)
ans =
1 1 1 1 1
1 1 1 2 0
1 1 3 0 0
1 2 2 0 0
2 3 0 0 0
A 0 indicates no number. If you want to remove the zeros, you need to put the result in the form of a cell array, where each cell is a vector with nonzero values:
result_cell = arrayfun(#(ii) result(ii, logical(result(ii,:))), 1:size(result,1), 'uniformoutput', 0);
In the example, this would give
>> result_cell{:}
ans =
1 1 1 1 1
ans =
1 1 1 2
ans =
1 1 3
ans =
1 2 2
ans =
2 3