Using matlabFunction with symbollic expression containing a matrix

1 view (last 30 days)
I have the following code, which gives me the error 'Dimensions do not match' when I use matlabFunction as below. I get the same error when I do alpha = matlabFunction(alpha, 'Vars', {[x, y, A]}). I am trying to use matlabFunction in order to increase the speed of subs. I have also tried matlabFunction(alpha, 'Vars', {symvar(alpha)}) but then I get the error 'Too many output arguments'
syms x [4 1] matrix
syms y [3 1] matrix
syms A [3 4] matrix
alpha = y.'*A*x
alpha = 
alpha = matlabFunction(alpha, 'Vars', {[y, A, x]})
Error using symbolic.mixin.symbolicmatrix/engineHelperWrapper
Dimensions do not match.

Error in symbolic.mixin.symbolicmatrix/horzcat (line 94)
Z = symbolic.mixin.symbolicmatrix.engineHelperWrapper('Dom::SymbolicMatrix::horzcat', X{:});

Answers (2)

Walter Roberson
Walter Roberson on 4 May 2023
y is 3 x 1. A is 3 x 4. [y, A] is valid and is 3 x 5.
x is 4 x 1. [3 x 5, 4 x 1] is a mismatch of dimensions.
The [y, A, x] has to succeed first before the resulting value could be passed into the 'Vars' option.
Effectively, when you use 'vars' with a cell array then each [] that you pass in must be a row vector, or a column vector, or a complete rectangular array.
You could use potentially use separate parameters for the [y, A] and x. Or you could put in some dummy variables, like
syms dummy1 [1 5]
alpha = matlabFunction(alpha, 'Vars', {[[y, A; dummy1], x]})
then [y, A; dummy1] would be 4 x 5 with the bottom row unused in the calculation, and the x would be to the right of that in the same array.
  2 Comments
Yash Ramani
Yash Ramani on 4 May 2023
Thank you for your answer.
I am sorry if I am missing something, but I don't understand where the 5 comes from. My intention was to convert alpha, which is of size 1×1 (given the dimensions of A, x, and y) to a function handle. The code above to achieve same, I got from elsewhere. From what I understand from your answer, my understanding that {[y, A, x]} serves to only specify the symbolic variables contained in alpha, was wrong. Could you please elaborate on what [y, A, x] achieves? Futhermore, what can I do so that alpha behaves like the function handle @(A, x, y) y.'*A*x?
Walter Roberson
Walter Roberson on 5 May 2023
When you use
alpha = matlabFunction(alpha, 'Vars', {[y, A, x]})
then it is not "just syntax" to use [y, A, x] . It is not like multiple assignment such as
[y, A, x] = unique(randi(5, 1, 50))
where the [] is just arbitrary syntax that could have been written some other way such as
<y, A, x> = unique(randi(5, 1, 50))
as minor change to the language design.
In the statement
alpha = matlabFunction(alpha, 'Vars', {[y, A, x]})
the parts follow MATLAB semantics. The name matlabFunction is encountered first, looked up to identify it as not being a reserved word, then you start processing the contents of the (). You mostly scan from left to right. alpha is encountered and that is the end of the parameter, so alpha is looked up and the pointer to the alpha variable is remembered. Then 'Vars' is examined and found to be a character vector, and a temporary variable containing that character vector is allocated and the pointer to that temporary vector is remembered.
Then the { of {[y, A, x]} is encountered and MATLAB starts building a cell array. Inside the cell array the list-building expression [y, A, x] is encountered. When you have comma-separated parts inside the [] list-building operator, the effect is to transform the [y, A, x] into horzcat(y, A, x) . So y is looked up and its data pointer is remembered, A is looked up and its data pointer is remembered, x is looked up and its data pointer is remembered, and the list of three data pointers is passed to the horzcat() function. In order to use horzcat(), the parts all have to have the same number of rows (and same number of hyperplanes) but do not have to have the same number of columns.
y has 3 rows and A has 3 rows, so horzcat(y, A) is valid . But x does not have 3 rows so horzcat(y,A,x) is not valid.
If y, A, x all had the same number of rows, then the single concatenated result (with multiple rows) would be returned back from the [] horzcat operation, and that would be the end of the parameters to the {} cell-array building operation so the [y,A,x] list would be wrapped inside a temporary cell array, and the data pointer to that temporary cell array would be remembered. Now the remembered data pointers to alpha, 'Vars' and {[y,A,x]} would be passed to matlabFunction()
The {[y, A, x]} is not magic syntax: it is regular MATLAB operations. And that requires that y, A, x be compatible for horizontal concatenation.
If the [y, A, x] worked then the effect of 'Vars', {[y, A, x]} would be to tell matlabFunction that the function is to expect a single parameter, and that inside the function, different elements of the single parameter are to be extracted to fill in for y, A, x in the expression.
... Which is not what you actually wanted. What you wanted was for y, A, x to be separate parameters. And the syntax for that would be
alpha = matlabFunction(alpha, 'Vars', [y, A, x])
Or, alternately,
alpha = matlabFunction(alpha, 'Vars', {y, A, x})

Sign in to comment.


VBBV
VBBV on 5 May 2023
Edited: VBBV on 5 May 2023
Can you tell why you would like to convert the symbolic matrix to anonymous function? The error you get is due to symbolic matrix input to matlabFunction to transform it to anonymous function
syms x [4 1] matrix
syms y [3 1] matrix
syms A [3 4] matrix
alpha = y.'*A*x
alpha = 
Alpha = matlabFunction(symmatrix2sym(alpha), 'Vars', {symmatrix2sym(y), symmatrix2sym(A), symmatrix2sym(x)})
Alpha = function_handle with value:
@(in1,in2,in3)in1(1,:).*(in2(1).*in3(1,:)+in2(4).*in3(2,:)+in2(7).*in3(3,:)+in2(10).*in3(4,:))+in1(2,:).*(in2(2).*in3(1,:)+in2(5).*in3(2,:)+in2(8).*in3(3,:)+in2(11).*in3(4,:))+in1(3,:).*(in2(3).*in3(1,:)+in2(6).*in3(2,:)+in2(9).*in3(3,:)+in2(12).*in3(4,:))
y = symmatrix2sym(alpha)
y = 
% if it were only scalars symbols
syms x
syms y
syms A
alpha = y.'*A*x
alpha = 
Alpha = matlabFunction(alpha, 'Vars', {y, A, x})
Alpha = function_handle with value:
@(y,A,x)A.*x.*y

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!