Matlab equivalent of Maple's remove_RootOf

조회 수: 2 (최근 30일)
Alec Jacobson
Alec Jacobson 2022년 11월 8일
댓글: Walter Roberson 2022년 11월 8일
I have a symbolic expression of the form root(…). I'd to recover the operand as a symbolic expression itself. I believe this would require the symbolic toolbox equivalent of maple's remove_RootOf function.
Here's a minified example (also interested in workarounds for what I'm trying to do, but I'd appreciate an answer to the direct original question, too):
syms('a');
syms('b');
syms('t');
sres = solve( b + (a - b)/t^2 - (t*b)/(t - 1)^2 == 0,t)
This results in:
sres =
root(b*z^4 - 3*b*z^3 + a*z^2 + 2*b*z - 2*a*z - b + a, z, 1)
root(b*z^4 - 3*b*z^3 + a*z^2 + 2*b*z - 2*a*z - b + a, z, 2)
root(b*z^4 - 3*b*z^3 + a*z^2 + 2*b*z - 2*a*z - b + a, z, 3)
root(b*z^4 - 3*b*z^3 + a*z^2 + 2*b*z - 2*a*z - b + a, z, 4)
What I'd like as an expression is
b*z^4 - 3*b*z^3 + a*z^2 + 2*b*z - 2*a*z - b + a
The reason that I want this is that I'd like to call roots to numerically solve for t given (many different) numerical values of a and b. I realize I could also do:
% Build a function that computes numerical roots using vpa
vroots = @(A,B) double(vpa(subs(sres,{a,b},[A,B])));
but this is 100× to 1000× slower than it's roots counterpart:
% Extreme hack to strip off 'roots('; strsplit is needed because str2sym will
% choke on longer inputs
spoly = sum(cellfun(@(s) str2sym(s),strsplit(regexprep(sprintf('%s',sres(1)),'^root\((.*),.*,.*$','$1'),' + ')));
syms('z');
polyfun = matlabFunction(flip(coeffs(spoly,z)),'Vars',{a,b});
% Build a function that computes numerical roots using roots. 100× to 1000×
% faster than vroots
nroots = @(A,B) roots(polyfun(A,B));
For example:
timeit(@()vroots(1,1)) / timeit(@()nroots(1,1))
results in something like 700 on my machine and both answers are high enough precision.
So, as you can see above. I currently have a pretty wild hack to get the expression from inside root(…) using string manipulation. Is there a more direct and less fragile way?

채택된 답변

Walter Roberson
Walter Roberson 2022년 11월 8일
편집: Walter Roberson 2022년 11월 8일
Use children()
Maybe arrayfun @(X)children(X, 1)
  댓글 수: 2
Alec Jacobson
Alec Jacobson 2022년 11월 8일
This is great! from children I can also get z symbolically so I don't have to hard code it.
Walter Roberson
Walter Roberson 2022년 11월 8일
Yes, getting the variable from the expression is best. I have very seldom seen it generate anything other than z even for nested rootOf, but I have seen z1 and z2 a small number of times.

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

제품


릴리스

R2020a

Community Treasure Hunt

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

Start Hunting!

Translated by