MATLAB Answers

matlabFunction: Index exceeds the number of array elements for Matlab R2021a

41 views (last 30 days)
Maximilian Stölzle
Maximilian Stölzle on 13 Apr 2021 at 7:30
Commented: Walter Roberson on 15 Apr 2021 at 9:25
Hi all,
I am currently trying to write a symbolic expression into a matlab function using the matlab command. This works perfectly for smaller symbolic expressions, but for larger ones I encounter the following error in R2021a:
matlabFunction(C, 'vars', {q, qdot, alpha, l, rho}, 'file', strcat(dpath,'/C_fun'), 'Optimize', true);
Index exceeds the number of array elements (54).
Error in sym/matlabFunction>addVars (line 817)
varArr = addElem(varArr,split(join(elem(start:ende),','),','));
Error in sym/matlabFunction>handleBlocks (line 928)
blocks(end).lhs = addVars(blocks(end).lhs, lhsVars, linesWritten+1,linesWritten+newLines);
Error in sym/matlabFunction>writeOutput (line 616)
blocks = handleBlocks(blocks, body, fmt, lhsVars, rhsVars, ifNargout);
Error in sym/matlabFunction>writeMATLAB (line 506)
blocks = writeOutput(outputs,f,1,sparseMat,blocks,false);
Error in sym/matlabFunction (line 196)
[g, blocks] = writeMATLAB(funs,file,varnames,outputs,body, opts.Optimize, opts.Sparse,
opts.Comments, blocks);
Is there a possibility to increase the maximal length of the matlabFunction command?

Accepted Answer

Walter Roberson
Walter Roberson on 15 Apr 2021 at 7:23
matlabFunction has a bug in writing any function using piecewise to a file in expression that is complicated enough that the function is not generated as a single line.
For example if it generates temporary code like
if ((q1 ~= 0.0) & (q2 ~= 0.0))
t3 = (1.0./q0.^2.*1.0./q2.^5.*(et100+et101+et102+et103+et104+et105+et106+et107+et108+et109+et110+et111+et112+et113+et114+et115+et116))./(q1.*1.0e+6);
else
t3 = NaN;
end
then in post-processing it will crash.
Internally, the code is assuming that each line of temporary code assigns to one (distinct) variable -- a pure sequence of assignment expressions. But notice in the above temporary code that the first, third, and fifth line do not assign to any variables, and that the variable assigned to in the fourth line is the same as the one assigned to on the second line. In such a situation, the code crashes.
I do not have any work-around at the moment. The logic of the relevant function is broken, but it also relies on mistaken infrastructure variables being carried around. The most natural fix would require changes to internal code of the Symbolic Engine.
This is going to require a repair from Mathworks.
  2 Comments
Walter Roberson
Walter Roberson on 15 Apr 2021 at 9:25
The error does not exist before R2021a. The R2021a matlabFunction() has substantial rewrites.
I just finished writing a bug report for Mathworks, so they will know as soon as they read my report.
If my analysis is correct, it is not only piecewise() that can lead to this problem, and that the problem can also occur an array of output is being created instead of a vector.
My analysis is that this is something that has no easy fix; the problem logic at the MATLAB level could potentially work (maybe) if the output from the MuPAD level were different. I think Mathworks might end up having to change what is emitted from MuPAD, as the alternative requires parsing the generated MATLAB code looking for assignment statements when there can be multiple assignments on the same line and can be a branching if/elseif structure; it would be more robust to change the MuPAD side.

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 13 Apr 2021 at 7:57
matlabFunction(C, 'vars', {q, qdot, alpha, l, rho}, 'file', strcat(dpath,'/C_fun'), 'Optimize', true);
Index exceeds the number of array elements (54).
You did not mention your release. I predict that you are using R2020a or before (and I am not positive it was fixed in R2020b though I was told i was). If so then you need to use 'Optimize', false .
Unfortunately in a range of versions of MATLAB, matlabFunction with 'optimize' turned on generates incorrect output when it produces output at all. It generates correct output to a point, and then gets messed up. Effects varied: sometimes it generated additional lines but did not use any of them, returning a partial result instead; sometimes (more rarely) it did not generate additional lines but tried to use the elements it would have generated, generating index out of range errors.
I have use matlabFunction to generate fairly large expressions. It can turn painfully slow (especially with optimize turned on.) A small number of releases ago, I think they mentioned that performance had been improved a fair bit, but I am not certain about that.
Note: When you use 'Optimize', 'on', then the matching process seems to be at least O(n^2.3) in my tests. Because of that, if you have an expression made up of adding or multiplying multiple parts, it can be much faster to generate functions for each of the parts individually, and then add an extra function to hook the parts together. Doing this can lose out on some optimizations, but it can cut down a lot when working with expressions that do not have much in common (because the optimizer does not know they do not have a lot in common.)
  4 Comments
Maximilian Stölzle
Maximilian Stölzle on 15 Apr 2021 at 5:48
Hi Walter,
Thank you so much. That would be great.
So first you need to load the C_matrix.mat in the attachment into your workspace.
Subsequently, we run the matlabFunction command:
matlabFunction(C, 'vars', {q, qdot, alpha, l, rho}, 'file', strcat(pwd,'/C_fun'), 'Optimize', false);
Best regards,
Maximilian

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!

Translated by