Evaluate Matrix on parametrized indices - arrays

I have a matrix, say F= magic(8), whose elements are indicesed by x and y in 1:N in both dimensions.
I have a (1-D) parameter that specifies a subset of the possible coordinates (x,y), i.e. x(b(k)) and y(b(k)) with size(b)=[M,1] give me
M coordinates (x(b(k)),y(b(k))) where I want to evaluate F.
Is it possible to access F((x(b(k)),y(b(k)))) for k=1:M without writing a for loop?
I am looking a quicker solution that running the loop
F= magic(8)
for k=1:M
do_something_on(F((x(b(k)),y(b(k)))))
end
Note that if I write
F((x(b(1:M)),y(b(1:M)))
I get a M x M matrix, where the diagonal elements are the ones I am looking for, but I rather do not build the whole M x M matrix to extract the diagonal.

Instead of F(x(b), y(b)) that is giving you a matrix, you can use:
arrayfun(#(bk) F(x(bk), y(bk)), b)
or:
F(sub2ind(size(F), x(b), y(b)))

I have probably found the solution, I have to use the vectorized form for the matrix F, that is F(:), and evaluate it in (y-1)*size(F,1)+x, i.e.
F((y(b)-1)*size(F,1)+x(b))

Related

Vectorization in Matlab, incomprehensible syntax difference causing failure

I fail to understand why, in the below example, only x1 turns into a 1000 column array while y is a single number.
x = [0:1:999];
y = (7.5*(x))/(18000+(x));
x1 = exp(-((x)*8)/333);
Any clarification would be highly appreciated!
Why is x1 1x1000?
As given in the documentation,
exp(X) returns the exponential eˣ for each element in array X.
Since x is 1x1000, so -(x*8)/333 is 1x1000 and when exp() is applied on it, exponentials of all 1000 elements are computed and hence x1 is also 1x1000. As an example, exp([1 2 3]) is same as [exp(1) exp(2) exp(3)].
Why is y a single number?
As given in the documentation,
If A is a rectangular m-by-n matrix with m~= n, and B is a matrix
with n columns, then x = B/A returns a least-squares solution of the
system of equations x*A = B.
In your case,
A is 18000+x and size(18000+x) is 1x1000 i.e. m=1 and n=1000, and m~=n
and B is 7.5*x which has n=1000 columns.
⇒(7.5*x)/(18000+x) is returning you least-squares solution of equations x*(18000+x) = 7.5*x.
Final Remarks:
x = [0:1:999];
Brackets are unnecessary here and it should better be use like this: x=0:1:999 ;
It seems that you want to do element-wise division for computing x1 for which you should use ./ operator like this:
y=(7.5*x)./(18000+x); %Also removed unnecessary brackets
Also note that addition is always element-wise. .+ is not a valid MATLAB syntax (It works in Octave though). See valid arithmetic array and matrix operators in MATLAB here.
‍‍‍‍‍‍ ‍‍ ‍‍‍‍‍‍ ‍‍3. x1 also has some unnecessary brackets.
The question has already been answered by other people. I just want to point out a small thing. You do not need to write x = 0:1:999. It is better written as x = 0:999 as the default increment value used by MATLAB or Octave is 1.
Try explicitly specifying that you want to do element-wise operations rather than matrix operations:
y = (7.5.*(x))./(18000+(x));
In general, .* does elementwise multiplication, ./ does element-wise division, etc. So [1 2] .* [3 4] yields [3 8]. Omitting the dots will cause Matlab to use matrix operations whenever it can find a reasonable interpretation of your inputs as matrices.

"Diagonalize" each row of a matrix

I have an n x p matrix that looks like this:
n = 100
p = 10
x <- matrix(sample(c(0,1), size = p*n, replace = TRUE), n, p)
I want to create an n x p x p array A whose kth item along the 1st dimension is a p x p diagonal matrix containing the elements of x[k,]. What is the most efficient way to do this in R? I'm looking for a way that uses outer (or some other vectorized approach) rather than one of the apply functions.
Solution using lapply:
A <- aperm(simplify2array(lapply(1:nrow(x), function(i) diag(x[i,]))), c(3,2,1))
I'm looking for something more efficient than this.
Thanks.
As a starting point, here is a humble for loop method with pre-allocation of the matrix.
# pre-allocate matrix of desired size
myArray <- array(0, dim=c(ncol(x), ncol(x), nrow(x)))
# fill in array
for(i in seq_len(nrow(x))) myArray[,,i] <- diag(x[i,])
It should run relatively fast. On my machine, for a 1000 X 100 matrix, the lapply method took 0.87 seconds, while the for loop (including the array pre-allocation) took 0.25 seconds to transform the matrix into to your desired array. So the for loop was about 3.5 times faster.
transpose your original matrix
Note also that row operations on R matrices tend to be slower than column operations. This is because matrices are stored in memory by column. If you transpose your matrix, and perform the operation this way, the time to complete the operation on 100X1000 matrix drops to 0.14, half that of the first for loop, and 7 times faster than the lapply method.

doing algebra with an MxNx3 array using vectorization in python?

Suppose I have an MxNx3 array A, where the first two indexes refer to the coordinates a point, and the last index (the number '3') refers to the three components of a vector. e.g. A[4,7,:] = [1,2,3] means that the vector at point (7,4) is (1,2,3).
Now I need to implement the following operations:
Lx = D*ux - (x-xo)
Ly = D*uy + (y-yo)
Lz = D
where D, ux, uy, xo, yo are all constants that are already known. Lx, Ly and Lz are the three components of the vector at each point (x,y) (note: x is the column index and y is the row index respectively). The biggest problem is about the x-xo and y-yo, as x and y are different for different points. So how to carry out these operations for an MxNx3 array efficiently, using vectorized code or some other fast methods?
thanks
You could use the meshgrid function from numpy:
import numpy as np
M=10
N=10
D=1
ux=0.5
uy=0.5
xo=1
yo=1
A=np.empty((M,N,3))
x=range(M)
y=range(N)
xv, yv = np.meshgrid(x, y, sparse=False, indexing='ij')
A[:,:,0]=D*ux - (xv-xo)
A[:,:,1]=D*uy - (yv-yo)
A[:,:,2]=D
If you want to operate on the X and Y values, you should include them in the matrix (or in other matrix) instead of relying in their indexes.
For that, you could use some of range creation routines from Numpy, specially numpy.mgrid.

MATLAB: efficient way to run a vector input function with an array input

I have a function HermitePCECoefficients which takes as inputs multiple parameters, including a column vector y, and outputs a column vector Coefficients, the same length as y:
Coefficients=HermitePCECoefficients(grid,weights,indices,y,mu,sigma,normalized)
Suppose now that y is not a column vector, but a 2D array (matrix), and I want to run HermitePCECoefficients on each of its columns, storing the corresponding outputs in a array. Doing it with a for loop is simple and clear, but it takes forever:
Coefficients=zeros(size(y));
for i=1:size(y,2)
Coefficients(:,i)=HermitePCECoefficients(grid,weights,indices,y(:,i),mu,sigma,normalized);
end
Thus, I put bsxfun to the job. Since bsxfun only works with binary functions, I created a "dummy" binary function f, which is really only a function of a single argument:
f=#(a,b) HermitePCECoefficients(grid,weights,indices,a,mu,sigma,normalized);
Then used bsxfun this way:
Coefficients=bsxfun(f,y,omega_f);
This works fine, and it's much faster than the for loop (don't worry about omega_f, it's just a vector whose length corresponds to the number of columns in y).
Question 1: do you think this is the right way to use bsxfun in this context?
Question 2: maybe a better solution would be to directly modify HermitePCECoefficients, so that it could take a generic array y as input. Inside the function, this is the only line which requires y to be a column vector:
Coefficients(i)=dot(weights,y.*Psi)/norm;
weights and Psi are two column vectors, so if I pass an array y, MATLAB complains. Any suggestions on how to modify it?
Option 2 seems better (but only testing will tell). Just replace
dot(weights,y.*Psi)/norm
by
sum(bsxfun(#times, weights.*Psi, y)/norm)
or (probably faster)
(weights.*Psi).'*y / norm
Either of the above is equivalent to computing the vector [ dot(weights,y(:,1).*Psi)/norm, dot(weights,y(:,2).*Psi)/norm, ... ] for an arbitrary number of columns of y. Each entry of this vector is the result for a column of y.
You could use repmat on weights and Psi to replicate the vectors across the columns of y:
nc = size(y,2);
Coefficients = dot(repmat(weights,1,nc), y.*repmat(Psi,1,nc))/norm;

Array - vector multiplication in R

I need a simple matrix-algebra or Kronicker product type operation to multiply an array and a vector in R to get to a specific result. Let's say I have the array:
ar<-array(c(rep(1,9),rep(10,9),rep(100,9)),dim=c(3,3,3))
And the vector c(1,2,3). Multiplying both by * multiplies each row on each slide of the array by 1,2, and 3 respectively. However, I need an operation to get to array
ar2<-array(c(rep(1,9),rep(20,9),rep(300,9)),dim=c(3,3,3))
instead. That is, is there a simple operation that would allow me to transform ar to ar2 using the vector I specified above? Thanks!
ar * rep(1:3, each=9) should work...
For an arbitrary sized array and an arbitrary set of multipliers, you know the dimensions of your array and the axis along which you want to perform your elementwise multiplication (in this case, the z axis):
each_arg <- prod(dim(ar)[1:2])
multipliers <- sample(1:10, 3)
ar2 <- ar * rep(multipliers, each=each_arg)
You can also look at the tensorA package

Resources