MATLAB: how to stack arrays "form-agnostically"?

Suppose that f is a function of a single parameter whose output is n-dimensional (m 1 x m 2 x hell m n ) and that B is a vector of length k whose elements are valid arguments for f .

I am looking for a convenient and, more importantly, "agnostic form" MATLAB expression (or recipe) for creating an (n + 1) -dimensional (m 1 × m 2 × × & hellip; × m n & times; k) an array obtained by "stacking" k n -dimensional arrays f(b) , where the parameter B is in the range B

To do this in numpy , I would use an expression like this:

 C = concatenate([f(b)[..., None] for b in B], -1) 

In the case of its use, I will unpack this numerical expression below (see APPENDIX ), but its feature, which I want to emphasize now, is that it is completely agnostic for figures / sizes f(b) and B For the types of applications that I have in mind, the ability to write such “formal agnostic” code is of paramount importance. (I emphasize this point because a lot of the MATLAB code that I come across for this kind of manipulation is clearly not “formally agnostic,” and I don't know how to do it.)


application

In the general case, if A is a numpy array, the expression A[..., None] can be considered as a “change of form" of A , so that it takes one additional, trivial dimension. Thus, if f(b) is n-dimensional (m 1 · m 2 · hellip; × m n ), then f(b)[..., None] is corresponding (n + 1) - dimensional (m 1 x m 2 x? hellip; m n x 1) array. (The reason for adding this trivial dimension will become apparent below.)

Given this clarification, the meaning of the first concatenate argument, namely:

 [f(b)[..., None] for b in B] 

not too hard to decrypt. This is a standard Python list comprehension, and it evaluates a sequence of k (n + 1) -dimensional (m 1 x m 2 x & hellip; x m n x 1) arrays f(b)[..., None] , since the parameter B runs through the vector B

The second argument to concatenate is the "axis" along which concatenation should be performed, expressed as an index of the corresponding dimension of the arrays to be combined. In this context, the -1 index plays the same role as the end keyword in MATLAB. Therefore, the expression

 concatenate([f(b)[..., None] for b in B], -1) 

says "combine the arrays f(b)[..., None] along their last dimension." This means that this “last dimension” is concatenated by the need to change the array f(b) (for example, f(b)[..., None] ).

+4
source share
2 answers

One way to do this:

  % input: f=@ (x) x*ones(2,2) b=1:3; %%%% X=arrayfun(f,b,'UniformOutput',0); X=cat(ndims(X{1})+1,X{:}); 

Perhaps there are more elegant solutions?

+6
source

The agnosticity of form is an important distinction between the philosophies underlying NumPy and Matlab; it is much more complicated in Matlab than in NumPy. And, in my opinion, the agnostic nature of the form is bad - the form of the matrices has mathematical meaning. If any function or class must completely ignore the shape of the inputs or change them in a way that does not correspond to the mathematical notation, then this function destroys part of the functionality and intent of the language.

In terms of programmers, this is a really useful feature designed to prevent forms-related errors. Of course, this is often a "software inconvenience", but there is no reason to adjust the language. This is really all in thinking.

Now, having said that, I doubt that Matlab has an elegant solution for your problem :) My suggestion was to fill all the requirements in a function, so that you do not need to do any post-processing:

 f = @(x) bsxfun(@times, permute(x(:), [2:numel(x) 1]), ones(2,2, numel(x)) ) 

Now, obviously, this is not entirely correct, since f(1) does not work, and f(1:2) does something different from f(1:4) , so it is obvious that some kind of intervention is necessary. But, as the ugliness of this oneliner already shows, a special feature might be a better idea. Oli, proposed by Oli, is pretty decent if you block it in your own function:

 function y = f(b) g = @(x)x*ones(2,2); %# or whatever else you want y = arrayfun(g,b, 'uni',false); y = cat(ndims(y{1})+1,y{:}); end 

so f(b) for any b creates the correct conclusion.

+1
source

Source: https://habr.com/ru/post/1434974/


All Articles