Symbolic multidimensional arrays with changable dimension
2 views (last 30 days)
Show older comments
Consider an integer n, p a 1x4 symbolic array and c a 4x4 symbolic matrix. Here Latin letters are denoting integer indexes that run from 1 to 4. I would like to compute the following n-multidimensional array (let us call it M)
How can I compute this quantity?
Here is an example. If
we have
. We can solve this with a for loop such that
M = sym(zeros(4, 4, 4));
syms x y z w
p = [x y z w];
c = [x y z w; x y z w; x y z w; x y z w];
for i = 1:4
for j = 1:4
for k = 1:4
M(i,j,k) = p(i)*c(i,j)*c(j,k);
end
end
end
How can I do this symbolically when n is not known a priori, but it is choosen by the user?
Thank you.
3 Comments
Bruno Luong
on 24 Mar 2022
Still a bad description, Should read:
"Consider an integer n, p a 1x4 array and c a 4x4 matrix. Here Latin letters are denoting integer indexes that run from 1 to 4. I would like to compute the following n-multidimensional array (let us call it M)"
Accepted Answer
Bruno Luong
on 24 Mar 2022
Edited: Bruno Luong
on 25 Mar 2022
p = [1 2 3 4];
c = [1 2 3 4; 1 2 3 4; 1 2 3 4; 1 2 3 4];
n=3;
M = p(:); % EDIT, bug fix
for k=1:n-1
cc = reshape(c, [ones(1,k-1) size(c)]);
M = M.*cc;
end
M
7 Comments
Bruno Luong
on 25 Mar 2022
Edited: Bruno Luong
on 25 Mar 2022
It works for me see the code I give and RUN.
Something you change that is not right.
More Answers (1)
Walter Roberson
on 24 Mar 2022
You have the implicit question of how you can do n nested loops where n is entered by the user.
There are two major ways:
First way:
You can use ndgrid to build cell arrays of elements that will be used in the calculations, or cell arrays of indices. The number of entries build can be dynamic:
n = 3;
T1 = cell(1,n);
[T1{:}] = ndgrid(sym(1:4)); %these will be individually multidimensional arrays
T2 = cellfun(@(M) M(:), T1, 'uniform', 0); %these will be individually column vectors
T2 = horzcat(T2{:});
whos T2
T2 will now be an array in which each row contains a combination of elements, and all possible combinations are listed. You could, for example, take
prod([p(T2(:,1)), c(T2(:,2:end))], 2)
... except if you are indeed going to use the T2 values as indices, you would not use the sym() in the ndgrid call.
This approach requires storing those intermediate multidimensional arrays, and that can add up to a lot of temporary memory.
Second way:
You can use what has sometimes been called an "odometer" pattern of programming. I gave general code for that in https://www.mathworks.com/matlabcentral/answers/623358-get-a-combination-of-unique-paths-for-given-pair-of-numbers#comment_1082638 -- and in there I do not assume that the values being selected from have the same datatype (you can be a bit more efficient if the values are all numeric.)
The odometer programming pattern at each point changes the last element of a vector to the next value. If it was already the last value possible, it rolls that position over to the first value for it, and then moves to the left and increments that value; if that was not already the last then it is done. If that one was the last possible for its position, it rolls it over to the first valid value for that position, and moves one left... and so on.
This only requires keeping storage for the current configuration, together with a vector that defines the valid values at each position. It does not require keeping multidimensional arrays.
The odometer pattern is not as fast as vectorization... when you have enough memory to do the vectorization. When you do not have enough memory to do the vectorization, then the odometer pattern is faster, in the sense that clearly eventually it will get through all of the patterns, and getting through all the patterns at some point is "faster" than not being able to get through all of the possibilities because you ran out of memory.
1 Comment
See Also
Categories
Find more on Logical in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!