Efficient Manipulation of Cell Array of Gridded Data Interpolant in Matlab - matlab

I have vectors Ll, Lh, x, and alp of sizes NL, NL, Nx, and Nalp, respectively. I also have a matrix G of size NL * NL * Nx * Nalp. G is a function of Ll, Lh, x, and alp. Together, I have gridded arrays and sample values in G.
For each x and alp, I create an interpolant and store in a cell array. See below code snippet:
for ixs=1:Nx
for ias=1:Nalp
Gn(:,:,ixs, ias)={griddedInterpolant({Ll, Lh}, G(:,:,ixs, ias),'linear', 'none')};
end
end
Pros: Compared to interp2, this is very fast especially because I have to evaluate Gn by a great number of times.
Cons: (1) Requires a great deal of memory, and (2) Cannot be easily vectorized so as to avoid an additional loop of the following kind (which is again evaluated many many times)
for ixs=1:Nx
for ias=1:Nalp
GGn=Gn{:,:, ixs, ias};
SomeVector(ixs, ias)*GGn(Llnx, Lhnx);
end
end
(a) If I could somehow vectorize the whole class of griddedInterpolant named Gn, I could optimize on the last loop, and (b) If I could store the vector Ll, and Lh only once, I could use memory more efficiently.
I need your help. Precisely, how can I do this more efficiently? Thank you.
Best,
BK
EDIT:
A solution would be to generate a function Gn which takes Ll and Lh as arguments, given x and alp. Gn returns an array of functional handles, one for each (x, alph). Then, calling Gn(Llnx, Lhnx, x, alp) returns the interpolated value. Now, (Llnx, Lhnx, x, alp) can each be arrays of the same number of elements. Any efficient way that uses professional's code?

Using the method provided here you can pre-compute weights for multidimensional linear interpolation. So you don't need griddedInterpolant and use bsxfun to vectorize computation of interpolation using the precomputed weights.
[W I]=lininterpnw(Ll, Lh, Llnx, Lhnx);
GGn = reshape(G,NL* NL,[]);
result = squeeze(sum(bsxfun(#times, W, reshape(GGn(I(:),:),size(G)))));
bsxfun(#times, reshape(SomeVector,1,[]), result);
Each column in the result matrix is the output of the interpolation of each 2D matrix.
Here assumed that 1Ll, Lh, Llnx, Lhnx are row vectors.

Related

Matlab: implementing sum of exponentials using function handles

I need to implement the following formula using function handles in Matlab
where t is the time vector and n is large. Also, Sk and fk are constant for each k. Any efficient way to implement this is appreciated.
Edit:
For the first harmonic, I could write
y=#(t) s(1)*exp(i*2*pi*f(1)*t);
However, I can not use this in a for loop to generate f(t). Is there a vector approach for doing this?
Assuming you have a data vector s, a frequency vector f of the same length, and a time vector t of a (potentially) different length, you can compute the given equation using
result = sum( s(:) .* exp( i*2*pi * f(:) .* t(:).' ), 1 );
What is happening here is s(:) forces s to be a column vector. We make f into a column vector in the same way. t(:).' is a row vector. MATLAB does implicit singleton expansion, so that f(:) .* t(:).' returns a 2D matrix. The other .* also does singleton expansion for s. Finally sum(.,1) sums over the fist dimension, which is over all values of f. The result is a row vector of the same length as t.
If you need a function handle that computes this, simply turn the one-liner into an anonymous function:
y = #(t) sum( s(:) .* exp( i*2*pi * f(:) .* t(:).' ), 1 );
This anonymous function will capture s and f as they exist when defining it. t can be supplied later:
result = y(t);
But do note that ifft does the same computation but much more efficiently.

How to raise a matrix to a vector of powers in matlab without for loop?

I have a 2x2 matrix that I want to multiply by itself 10 times while storing the result after each multiplication. This can easily be done with a for loop but I would like to vectorize it an eliminate the for loop. My approach was to have my 2x2 matrix a and raise it to a vector b with elements 1:10. The answer should be a 2x2x10 matrix that replicates typing
a^b(1)
a^b(2)
.
.
.
a^b(10)
To clarify I'm not doing this element wise I need actual matrix multiplication, and prefer not to use a for loop. Thanks for any help you can give me.
here is the code for you. I use the cellfun to do this and I have comments after each line of the code. It can compute and store from fisrt - nth order of the self-multiplication of an arbitrary matrix m. If you have any question, feel free to ask.
function m_powerCell = power_store(m, n) %m is your input matrix, n is the highest power you want to reach
n_mat = [1:n]; %set a vector for indexing each power result in cell
n_cell = mat2cell(n_mat,1,ones(1,n)); %set a cell for each of the power
m_powerCell = cellfun(#(x)power(m, x), n_cell, 'uni', 0); %compute the power of the matrix
end
%this code will return a cell to you, each element is a matrix, you can
%read each of the matrix by m_powerCell{x}, x represents the xth order

Matlab: definite integral of numerical vectors

i'm looking for to solve a definite integral of two vectors, I try to explain.
I know: z vector of numbers and G(z) vector of numbers.
The limits of integration are zmin and zmax
I should to calculate:
Integral between zmin,zmax of [G(z) * z^(7/6)] dz
Could I solve with the following code?
For i = zmin:zmax
myresult = G(z(i))*z(i)^(7/6)
end
(wrote before)
You can use numerical integral.
Define G(z) as a function handle, and the function to be integrated as
another one. You can find an example in my other answer.
So your goal is to calculate the sum of [G(z) * z^(7/6)] * dz, where G(z) and z are pre-calculated numerical vectors, dz a small increment value.
dz = (zmax - zmin) / length(G(z));
S = G * z' * dz;
S should be the result. Let me explain.
First of all, I messed up with G(z) previously (apologize for that). You have already evaluated (partially) the function to integrate, namely G(z) and z.
G(z) and z are number arrays. Arrays are indexed by integer, starting from 1. So G(z(i)) may not be a valid expression, as z(i) haven't been guaranteed to be integers. The code above only works correctly if you have defined G(z) in this way - G(i) = some_function (z(i));. By so each element of the same index in two arrays have a meaningful relation.
There are several ways to evaluate the product of two arrays (vectors), generating a single-value sum. A for loop works, but is inefficient. G * z' is the way to calc vector dot product.

Calculating the covariance of a 1000 5x5 matrices in matlab

I have a 1000 5x5 matrices (Xm) like this:
Each $(x_ij)m$ is a point estimate drawn from a distribution. I'd like to calculate the covariance cov of each $x{ij}$, where i=1..n, and j=1..n in the direction of the red arrow.
For example the variance of $X_m$ is `var(X,0,3) which gives a 5x5 matrix of variances. Can I calculate the covariance in the same way?
Attempt at answer
So far I've done this:
for m=1:1000
Xm_new(m,:)=reshape(Xm(:,:,m)',25,1);
end
cov(Xm_new)
spy(Xm_new) gives me this unusual looking sparse matrix:
If you look at cov (edit cov in the command window) you might see why it doesn't support multi-dimensional arrays. It perform a transpose and a matrix multiplication of the input matrices: xc' * xc. Both operations don't support multi-dimensional arrays and I guess whoever wrote the function decided not to do the work to generalize it (it still might be good to contact the Mathworks however and make a feature request).
In your case, if we take the basic code from cov and make a few assumptions, we can write a covariance function M-file the supports 3-D arrays:
function x = cov3d(x)
% Based on Matlab's cov, version 5.16.4.10
[m,n,p] = size(x);
if m == 1
x = zeros(n,n,p,class(x));
else
x = bsxfun(#minus,x,sum(x,1)/m);
for i = 1:p
xi = x(:,:,i);
x(:,:,i) = xi'*xi;
end
x = x/(m-1);
end
Note that this simple code assumes that x is a series of 2-D matrices stacked up along the third dimension. And the normalization flag is 0, the default in cov. It could be exapnded to multiple dimensions like var with a bit of work. In my timings, it's over 10 times faster than a function that calls cov(x(:,:,i)) in a for loop.
Yes, I used a for loop. There may or may not be faster ways to do this, but in this case for loops are going to be faster than most schemes, especially when the size of your array is not known a priori.
The answer below also works for a rectangular matrix xi=x(:,:,i)
function xy = cov3d(x)
[m,n,p] = size(x);
if m == 1
x = zeros(n,n,p,class(x));
else
xc = bsxfun(#minus,x,sum(x,1)/m);
for i = 1:p
xci = xc(:,:,i);
xy(:,:,i) = xci'*xci;
end
xy = xy/(m-1);
end
My answer is very similar to horchler, however horchler's code does not work with rectangular matrices xi (whose dimensions are different from xi'*xi dimensions).

'Multiplying' arrays in MATLAB

First off, I didn't know what to put as title, since the question is not easy to formulate shortly.
I need to convolve a matrix-valued function (k) with a vector-valued function (X), each of which is defined on R^3. I need to to this in MATLAB, so naturally I will do the discretized version. I plan on representing k and X by 5- and 4-dimensional arrays, respectively. This seems a bit heavy though. Do you know if there are any better ways to do it?
Instead of doing the convolution directly, I will go to Fourier space by fft'ing both k and X, pad with zeros, multiply them and then use ifft. That should produce the same result and run much, much faster.
My question here is whether there is any way to multiply these arrays/matrices easily? I.e. is there any way to do k(i,j,k,:,:)*X(i,j,k,:) for all i,j,k, without using three nested loops?
Do you need to discretize? Matlab is perfectly capable of taking functions as input and output. For examples, you could define a convolution function:
>> convolve = #(fm,fv) #(x) fm(x) * fv(x); %fm matrix valued, fv vector valued
and define some matrix-valued and vector-valued functions (this assumes the input is a column vector)
>> f = #(x) [x x x];
>> g = #(x) cos(x);
now their convolution:
>> h = convolve(f,g);
and try applying it to a vector:
>> h([1;2;3])
ans =
-0.8658
-1.7317
-2.5975
You get the same answer as if you did the operation manually:
>> f([1;2;3]) * g([1;2;3])
ans =
-0.8658
-1.7317
-2.5975
You perform element-by-element operation by using . together with the operator of choice. For example:
Element-by-element multiplication: .*
Element-by-element division: ./
and so on... is that what you mean?