How to solve :'Error using prod. Invalid data type. First argument must be numeric or logical.'

Hi,
In this part of the code:
--------------------------------------
if (prod(children(Term(ll)))~=Term(ll))
AAA=size(children(Term(ll)));
Chi(ll,1:AAA(1,2))=children(Term(ll));
Chi(ll,:)=expand(Chi(ll));
else
AAA=[1 1];
Chi(ll,1:1)=Term(ll);
end
---------------------------------------
I get the following error:
---------------------------------------
Error using prod
Invalid data type. First argument must be numeric or logical.
Error in Generalized_Integration_Code (line 130)
if (prod(children(Term(ll)))~=Term(ll))
----------------------------------------
Can you please help me how can I solve the error?
Thanks

 Accepted Answer

"Starting in R2020b, the syntax subexpr = children(expr) for a scalar input expr returns subexpr as a nonnested cell array instead of a vector"
So you will need to replace
prod(children(Term(ll)))
with
prod([struct('T',children(Term(ll))).T{:}])
Or previously construct
symcell2mat = @(v) [v{:}]
with
prod(symcell2mat(children(Term(ll))))

8 Comments

I think your answer is correct
But can you please explain more about this:
prod([struct('T',children(Term(ll))).T])
also:
symcell2mat = @(v) [v{:}]
with
prod(symcell2mat(children(Term(ll))))
Thanks.
[struct('T',children(Term(ll))).T]
is a syntax "cheat" in MATLAB.
children() in what you are doing is returning a cell array of symbolic expressions.
In order to use that with prod(), you need to turn the cell array of symbolic expressions into a vector of symbolic expressions.
If this were numeric work you were doing, then the easiest way to turn a cell array of numeric values into a vector is to use cell2mat(). Unfortunately, cell2mat() does not support symbolic expressions.
cell2mat() is a convenience routine that can handle non-scalars, but in this particular case of a row vector of values, cell2mat(X) effectively executes [X{:}] which is also known as horzcat(X{:}] . The {:} part means to do "cell expansion" -- the effect is the same as-if at that point the user had written out X{1},X{2}, X{3} all the way to the last entry. So [X{:}] is the same as [X{1},X{2},X{3},...X{end}] . And cell2mat() does that nicely in a clearly-named manner for numeric values, but cell2mat() refuses to work for symbolic expressions even though the same [X{:}] is all that would be needed.
You might hope that you could do
[children(Term(ll)){:}]
but MATLAB does not permit {:} indexing of the result of a function call.
So... at this point you have several choices to convert the cell array into a vector:
A) You can write out the code by hand, in long form:
TermChildren = children(Term(ll));
if prod([TermChildren{:}]) ~= Term(ll)
This requires at least one assignment to a temporary variable.
B) You can define an extra function such as
symcell2mat = @(v) [v{:}]
after which anywhere you wanted to convert a cell array of symbolic expressions into a vector of symbolic expressions you can call upon symcell2mat, like
if prod(symcell2mat(children(Term(ll)))) ~= Term(ll)
This kind of auxillary helper function is very useful, and can make code clearer -- but some people have trouble understanding using helper functions, and do not like to do that.
C) You can use the official MATLAB syntax for doing in-line expansion:
if prod([subsref(children(Term(ll)), struct('type', '{}', 'subs', {':'}))]) ~= Term(ll)
This is supported syntax based upon the way that indexing is implemented. But it is clearly ugly and confusing and tricky to remember the details of
D) You can use a syntax cheat. I mentioned above that MATLAB does not permit {:} of the results of a function call. But it does permit {:} indexing of a struct field, and it permits struct field indexing of the result of a function call. So if you have a function call FUN(X) and you want to index the results, then instead of using complicated subref(), you can use struct() to match the results of FUN(X) with a field name, and then you can use the fact that structs returned from functions can be field indexed. Thus
if prod([struct('T',children(Term(ll))).T{:}]) ~= Term(ll)
means to execute children(Term(ll)) and wrap it inside a struct with field name T, and then make use of the fact that you can struct index the results of a function call to pull out the T field. Then when you have the T field (which is just the result of the children() call) you can use {:} indexing on it and [] around that {:} indexing so that you end up with a vector of symbolic expressions; which you can then prod().
I do not recommend this approach. I only use it when it is momentarily important to prove that it can be done, or else when it feels too complicated at the time to explain to the person that they should split up the calculations into multiple lines or learn how to use helper functions.
AAA=size(children(Term(ll)));
That line can stay.
Chi(ll,1:AAA(1,2))=children(Term(ll));
That line will not work unless Chi is defined as a cell array.
Chi(ll,:)=expand(Chi(ll));
That line is going to fail. The right hand side should be expand(Chi(ll,:))
I would recommend rewriting the whole section:
TermChildren = children(Term(ll));
TermChildren = [TermChildren{:}];
if prod(TermChildren) ~= Term(ll)
Chi(ll, 1:length(TermChilden)) = expand(TermChildren);
AAA = size(TermChildren);
else
Chi(ll,1) = Term(ll);
AAA = [1 1];
end
Thank you very much for your comprehensive explanation.
I examine and I will inform the result.
Unrecognized function or variable 'TermChilden'.
Error in Generalized_Integration_Code (line 133)
Chi(ll, 1:length(TermChilden)) = expand(TermChildren);
Chi(ll, 1:length(TermChildren)) = expand(TermChildren);
instead of
Chi(ll, 1:length(TermChilden)) = expand(TermChildren);
The case where the product of the children is not equal to the original is simply the case where the original item is not a product. Which is something that could be tested using isSymType testing for numbers or variables or 'times'.

Sign in to comment.

More Answers (1)

We've no way of running your code, but I'm pretty certain if you just examine,
K>> class(children(Term(ll)))
all will be clear.

10 Comments

I am a beginner in MATLAB
K>> class(children(Term(ll)))
Can you please explain more about this?
If
KK = class(children(term(ll)))
does not give numeric or logical as result, you cannot apply prod.
So output KK.
This code runs in my professor system with MATLAB R2020 without any errors.
How to get an error in my system with MATLAB R2021b??
if (prod(children(Term(ll)))~=Term(ll))
AAA=size(children(Term(ll)));
Chi(ll,1:AAA(1,2))=children(Term(ll));
Chi(ll,:)=expand(Chi(ll));
else
AAA=[1 1];
Chi(ll,1:1)=Term(ll);
end
If there's a difference in the two codes, it was in the creation of 'children', not any part of the code you've posted. The error message is certainly not Matlab-version related. prod() will not work on cells and never has.
children=[1,2,3];
prod(children),
ans = 6
children={1,2,3};
prod(children)
Error using prod
Invalid data type. First argument must be numeric or logical.
All parts of the code are the same
The code is exactly the same in both systems.
I wonder why this is happening??
Likely because of Walter's answer. Regardless, full clarity can only come if you attach children in a .mat file.
Mathworks changed the output of children() to make the output for scalar input more consistent with the output for non-scalar input. Both cases now return cell array.

Sign in to comment.

Categories

Find more on Function Creation 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!