I have a row vector x in Matlab which contains 164372 components. I now want to group these elements in another vector y, which has to contain 52 components. The first element of the vector y must be the average of the first 164372 / 52 = 3161 elements of the vector x, the second element of y must be the average of the next 3161 elements of x, etc. This continues until I have taken all of the 52 averages of the elements in the vector x and placed them in y.
How can I implement this in Matlab? Is there some built-in function that lets me sum elements from a certain index to another index?
Thank you kindly for any help!
With reshape and mean:
x = rand(1,164372); % example data
N = 52; % block size. Assumed to divide numel(x)
result = mean(reshape(x, numel(x)/N, []), 1)
What this does is: reshape the vector into a 52-row matrix in the usual column-major order, and then compute the mean of each column.
Related
I implemented a finite differences algorithm to solve a PDE.
The grid is a structured 2D domain of size [Nx, Nz], solved Nt times.
I pre-allocate the object containing all solutions:
sol = zeros(Nx, Nz, Nt, 'single') ;
This becomes very easily too large and I get a 'out of memory' error.
Unfortunately sparse doesn't work for N-dimensional arrays.
For the sake of the question it's not important to know the values, it goes without saying that the RAM usage grows exponentially with decreasing the grid spacing and increasing the simulation time.
I am aware that I do not need to store each time instant for the purpose of the advancement of the solution. It would be sufficient to just store the previous two time steps. However, for post-processing reasons I need to access the solution at all time-steps (or at least at a submultiple of the total number).It might help to specify that, even after the solution, the grid remains predominantly populated by zeros.
Am I fighting a lost battle or is there a more efficient way to proceed (other type of objects, vectorization...)?
Thank you.
You could store the array in sparse, linear form; that is, a column vector with length equal to the product of dimensions:
sol = sparse([], [], [], Nx*Nz*Nt, 1); % sparse column vector containing zeros
Then, instead of indexing normally,
sol(x, z, t),
you need to translate the indices x, z, t into the corresponding linear index:
For scalar indices you use
sol(x + Nx*(z-1) + Nx*Nz*(t-1))
You can define a helper function for convenience:
ind = #(sol, x, y, t) sol(x + Nx*(z-1) + Nx*Nz*(t-1))
so the indexing becomes more readable:
ind(sol, x, z, t)
For general (array) indices you need to reshape the indices along different dimensions so that implicit expansion produces the appropriate linear index:
sol(reshape(x,[],1,1) + Nx*(reshape(z,1,[],1)-1) + Nx*Nz*(reshape(t,1,1,[])-1))
which of course could also be encapsulated into a function.
Check that the conversion to linear indexing works (general case, using non-sparse array to compare with normal indexing):
Nx = 15; Nz = 18; Nt = 11;
sol = randi(9, Nx, Nz, Nt);
x = [5 6; 7 8]; z = 7; t = [4 9 1];
isequal(sol(x, z, t), ...
sol(reshape(x,[],1,1) + Nx*(reshape(z,1,[],1)-1) + Nx*Nz*(reshape(t,1,1,[])-1)))
gives
ans =
logical
1
You can create a a cell array of sparse matrices to store the results. However computations can be performed on full matrices if working with a full matrix is faster than sparse matrix and convert the full matrix to sparse matrix and place it in the cell.
A sparse matrix is a large matrix with almost all elements of the same value (typically zero). The normal representation of a sparse matrix takes up lots of memory when the useful information can be captured with much less. A possible way to represent a sparse matrix is with a cell vector whose first element is a 2-element vector representing the size of the sparse matrix. The second element is a scalar specifying the default value of the sparse matrix. Each successive element of the cell vector is a 3-element vector representing one element of the sparse matrix that has a value other than the default. The three elements are the row index, the column index and the actual value. Write a function called sparse2matrix that takes a single input of a cell vector as defined above and returns the output argument called matrix, the matrix in its traditional form.
cellvec = {[2 3], 0, [1 2 3], [2 2 -3]};
matrix = sparse2matrix(cellvec)
matrix =
0 3 0
0 -3 0
By the information in the question :
In vector cell arrays it is usually the first vector used as a sparse
matrix dimension
The second element is a scalar specifying the default value of the
sparse matrix
The other vectors are used to specify the location and the value of
the element in the sparse matrix , i.e. [i, j, x] where i,j is the location
in the matrix and x is the value of the element.
So the program is simply :
function matrix=sparse2matrix(cellvec);
matrix=zeros(cellvec{1})+cellvec{2};
for i=3:length(cellvec)
matrix(cellvec{i}(1,1),cellvec{i}(1,2))=cellvec{i}(3);
end
Similarity number for two arrays X and Y, each with size N, is defined as the number of pairs of indices (i,j) such that X[i]=Y[j] , for 1<=i,j
Now we are given two arrays, of size N and M. We need to find the number of sub arrays of equal sizes from these two arrays such that the similairty number of each subarray pair is greater or equal to given number K.
Example, say we have N=3, M=3, K=1 and arrays be [1,3,4] and [1,5,3] then here answer is 6
Explanation :
({1},{1})
({3},{3})
({1,3},{1,5})
({1,3},{5,3})
({3,4},{5,3})
({1,3,4},{1,5,3})
so ans = 6
How to solve it for given arrays of size N,M and given integer K.
Number of elements can't be more than 2000. K is also less than N*M
Approach :
Form all subarrays from array 1 of size N, those will be N*(N+1)/2 And same for array 2 of size M. Then try to find similarity number between each subarray pair. But this is very unoptimised way of doing it.
What can be better way to solve this problem ? I think Dynamic programming can be used to solve this. Any suggestions ?
For {1,1,2} and {1,1,3} and K=1
{[1(1)],[1(1)]}
{[1(1)],[1(2)]}
{[1(2)],[1(1)]}
{[1(2)],[1(2)]}
{[1(1),1(2)],[1(1)]}
{[1(1),1(2)],[1(2)]}
{[1(1)],[1(1),1(2)]}
{[1(2)],[1(1),1(2)]}
{[1(1),1(2)],[1(1),1(2)]}
{[1(2),2],[1(2),3]}
{[1(1),1(2),2],[1(1),1(2),3]}
Since the contest is now over, just for the sake of completeness, here's my understanding of the editorial answer there (from which I learned a lot). Let's say we had an O(1) time method to calculate the similarity of two contiguous subarrays, one from each array, of length l. Then, for each pair of indexes, (i, j), we could binary search the smallest l (extending, say to their left) that satisfies similarity k. (Once we have the smallest l, we know that any greater such l also has enough similarity and we can add those counts in O(1) time.) The total time in this case would be O(M * N * log(max (M,N)).
Well, it turns out there is a way to calculate the similarity of two contiguous subarrays in O(1): matrix prefix-sums. In a matrix, A; where each entry, A(i,j), is 1 if the first array's ith element equals the second array's jth element and 0 otherwise; the sum of the elements in A in the rectangle A(i-l, j-l), A(i,j) (top-left to bottom-right) is exactly that. And we can calculate that sum in O(1) time with matrix prefix-sums, given O(M*N) preprocessing.
I have a binary 3D array of the size 1024 by 1024 by 1024. I want to use a function (convhull), which has the following input:
X is of size mpts-by-ndim, where mpts is the number of points and ndim is the dimension of the space where the points reside, 2 ≦ ndim ≦ 3
How can I reshape my array into the array X which is required by this function?
Maybe "reshape" isn't the best word, because using the "reshape" function isn't enough.
What convhull is looking for is a list of subscripts of nonzero elements in your array. Given a 3D array M:
[X,Y,Z] = ind2sub(size(M), find(M));
Then you use these in convhull:
convhull(X, Y, Z);
The lone X parameter you mention in your question is just these three column vectors concatenated:
X = [X Y Z];
convhull(X);
Given an array of ints with size t, one needs to find the center index. The center index x is the index where the sum of ints (0 to x-1) is equal to sum (x+1 to t-1).
The best algorithm I could come up with is O(n).
I would have a temp array with the sums of all ints before (not including the one at index x) : so at index 1 it would be 1, at 2 it would be a sum of 2 and 1 and so on.
Another int would be the sum of all ints.
I would loop twice through the array, the first make the temp array, and the other to find if both parts are equal.
Is there a better algorithm O(logn)?
Since you have to calculate the sum of both the half of the array, this can't be solved in less than O(n). Because you have to inspect each element at least once (to calculate the sum). Any algorithm can be logn only if we can skip inspecting certain elements of the array based on some condition which is not possible here.