rhombidodecahedron
rhombidodecahedron

Reputation: 7922

Generating a grid in matlab with a general number of dimensions

Problem

I have a vector w containing n elements. I do not know n in advance.

I want to generate an n-dimensional grid g whose values range from grid_min to grid_max and obtain the "dimension-wise" product of w and g.

How can I do this for an arbitrary n?


Examples

For simplicity, let's say that grid_min = 0 and grid_max = 5.

Case: n=1

>> w = [0.75];
>> g = 0:5

ans =

     0     1     2     3     4     5

>> w * g

ans =

         0    0.7500    1.5000    2.2500    3.0000    3.7500

Case: n=2

>> w = [0.1, 0.2];
>> [g1, g2] = meshgrid(0:5, 0:5)

g1 =

     0     1     2     3     4     5
     0     1     2     3     4     5
     0     1     2     3     4     5
     0     1     2     3     4     5
     0     1     2     3     4     5
     0     1     2     3     4     5


g2 =

     0     0     0     0     0     0
     1     1     1     1     1     1
     2     2     2     2     2     2
     3     3     3     3     3     3
     4     4     4     4     4     4
     5     5     5     5     5     5

>> w(1) * g1 + w(2) * g2

ans =

         0    0.1000    0.2000    0.3000    0.4000    0.5000
    0.2000    0.3000    0.4000    0.5000    0.6000    0.7000
    0.4000    0.5000    0.6000    0.7000    0.8000    0.9000
    0.6000    0.7000    0.8000    0.9000    1.0000    1.1000
    0.8000    0.9000    1.0000    1.1000    1.2000    1.3000
    1.0000    1.1000    1.2000    1.3000    1.4000    1.5000

Now suppose a user passes in the vector w and we do not know how many elements (n) it contains. How can I create the grid and obtain the product?

Upvotes: 5

Views: 494

Answers (1)

Luis Mendo
Luis Mendo

Reputation: 112689

%// Data:
grid_min = 0;
grid_max = 5;
w = [.1 .2 .3];

%// Let's go:    
n = numel(w);
gg = cell(1,n);
[gg{:}] = ndgrid(grid_min:grid_max);
gg = cat(n+1, gg{:});
result = sum(bsxfun(@times, gg, shiftdim(w(:), -n)), n+1);

How this works:

The grid (variable gg) is generated with ndgrid, using as output a comma-separated list of n elements obtained from a cell array. The resulting n-dimensional arrays (gg{1}, gg{2} etc) are contatenated along the n+1-th dimension (using cat), which turns gg into an n+1-dimensional array. The vector w is reshaped into the n+1-th dimension (shiftdim), multiplied by gg using bsxfun, and the results are summed along the n+1-th dimension.

Edit:

Following @Divakar's insightful comment, the last line can be replaced by

sz_gg = size(gg);
result = zeros(sz_gg(1:end-1));
result(:) = reshape(gg,[],numel(w))*w(:);

which results in a significant speedup, because Matlab is even better at matrix multiplication than at bsxfun (see for example here and here).

Upvotes: 8

Related Questions