matlab vectorization bsxfun

Generando arreglos usando bsxfun con función anónima y para restas de elementos-MATLAB



vectorization (1)

Tengo el siguiente código:

n = 10000; s = 100; Z = rand(n, 2); x = rand(s, 1); y = rand(s, 1); fun = @(a) exp(a);

En principio, la función anónima f puede tener una forma diferente. Necesito crear dos matrices.

Primero, necesito crear una matriz de tamaño nxsxs con elementos genéricos

fun(Z(i, 1) - x(j)) * fun(Z(i, 2) - y(k))

donde i=1,...n mientras j,k=1,...,s . Lo que puedo hacer fácilmente, es construir matrices usando bsxfun , por ejemplo

bsxfun(@(x, y) fun(x - y), Z(:, 1), x''); bsxfun(@(x, y) fun(x - y), Z(:, 2), y'');

Pero luego necesitaría combinarlos en una matriz 3D multiplicando elementos por cada columna de esas dos matrices.

En el segundo paso, necesito crear una matriz de tamaño nx 3 xsxs , que se vería desde un lado como la siguiente matriz

[ones(n, 1), Z(:, 1) - x(i), Z(:, 2) - y(j);]

donde i=1,...s , j=1,...s . Podría recorrer las dos dimensiones extra con algo como

A = [ones(n, 1), Z(:, 1) - x(1), Z(:, 2) - y(1)]; for i = 1:s for j = 1:s A(:, :, i, j) = [ones(n, 1), Z(:, 1) - x(i), Z(:, 2) - y(j);]; end end

¿Hay alguna manera de evitar los bucles?

En el tercer paso, supongamos que después de obtener array out1 (salida desde el primer paso), quiero crear una nueva matriz out3 de dimensión nxnxsxs , que contiene la matriz original out1 en la diagonal principal, es decir, out3(i,i,s,s) = out1(i, s, s) y out3(i,j,s,s)=0 para todo i~=j . ¿Hay algún tipo de alternativa de diag para crear "arreglos diagonales"? De forma alternativa, si creo nxnxsxs array de ceros, ¿hay alguna manera de poner out1 en la diagonal principal?


Código

exp_Z_x = exp(bsxfun(@minus,Z(:,1),x.'')); %//'' exp_Z_y = exp(bsxfun(@minus,Z(:,2),y.'')); %//'' out1 = bsxfun(@times,exp_Z_x,permute(exp_Z_y,[1 3 2])); Z1 = [ones(n,1) Z(:,1) Z(:,2)]; X1 = permute([ zeros(s,1) x zeros(s,1)],[3 2 1]); Y1 = permute([ zeros(s,1) zeros(s,1) y],[4 2 3 1]); out2 = bsxfun(@minus,bsxfun(@minus,Z1,X1),Y1); out3 = zeros(n,n,s,s); %// out3(n,n,s,s) = 0; could be used for performance out3(bsxfun(@plus,[1:n+1:n*n]'',[0:s*s-1]*n*n)) = out1; %//'' %// out1, out2 and out3 are the desired outputs