Shorten computation time for solving recursive equation
1 vue (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Jerry Yeung
le 17 Mar 2021
Modifié(e) : Walter Roberson
le 24 Mar 2021
Greetings.
I'm trying to solve a recursive symbolic equation. a is the variable I'm solving for and c, d and e are constants. It goes like this:
var = c+d*a/(1-e*a);
for 1:N
var=c+d*(var)/(1-e*var);
end
Then I set var == 0 and numerically solve for a. It takes a very long time for Matlab to solve when N increases, even with a decent initial guess. Is there any way to shorten the computation time?
Thanks.
2 commentaires
Walter Roberson
le 17 Mar 2021
What sort of order of magnitude is N ?
And how are you doing the numeric solving?
The small test I just did with N = 10 generated a var with powers of a above 1300 (display got too wide at that point); vpasolve() of that without any initial condition would try to find all 1300+ roots.
What sort of magnitude are c and d? I just tested with 2 and 9, and the terms involved coefficients up to about 10^1382 -- far too large for double precision to be useable.
Réponse acceptée
Walter Roberson
le 17 Mar 2021
Modifié(e) : Walter Roberson
le 17 Mar 2021
N = 100;
c = complex(randn,randn); d = complex(randn,randn); e = complex(randn,randn);
c = c./abs(c).*rand; d = d./abs(d).*rand; e = e./abs(e).*rand;
disp([c,d,e])
tic
syms a
var = c+d*a/(1-e*a);
for K = 1:N
var = simplify(c+d*(var)/(1-e*var));
end
toc
tic
A = solve(var);
toc
3 commentaires
Walter Roberson
le 18 Mar 2021
Modifié(e) : Walter Roberson
le 24 Mar 2021
There is a possibility that working purely numerically might work. That is, instead of calculating the formula and solve() it, instead accept a numeric trial a, run through the loop numerically, and fsolve() the whole thing or something like that.
That said, I seem to be having difficulty getting the numeric form to work, whereas the symbolic form works fine (see the cross-check.)
This has a few potential explanations:
- there might not be enough precision in doubles to resolve the equations; you might need to balance expressions to more than 16 digits
- the simplify() step that reduces the formula to make the solve() fast, might be implicitly gaining precision by reordering operations -- fewer terms evaluated with a specific a might drastically reduce the round-off problems
- there might be sub-expressions underflowing to 0 when done numerically. If you look at the function being solved for 0 in the symbolic version, you will find it involves terms with values on the order of 1E+3600. We are not seeing inf in the numeric versions of the calculation, but perhaps some of the terms underflow below 1e-308 and we lose the balance.
outer
function outer
rng(655321)
N = 100;
c = complex(randn,randn); d = complex(randn,randn); e = complex(randn,randn);
c = c./abs(c).*rand; d = d./abs(d).*rand; e = e./abs(e).*rand;
disp([c,d,e])
tic
guess = 2;
[Anum, fval] = fmincon(@calculate_a_numerically, guess);
Anum_time = toc;
fprintf('numeric determined a was %.16g in %.5f seconds\nResidue: ', Anum, Anum_time);
disp(fval)
tic
Asym = calculate_a_symbolically();
Asym_time = toc;
fprintf('symbolic determined a was %.16g in %.5f seconds\n', Asym, Asym_time);
crosscheck_sym_num = calculate_a_numerically(double(Asym))
crosscheck_sym_sym = calculate_a_symbolically(Asym)
function A = calculate_a_symbolically(a) %nested function!
if nargin < 1;
a = sym('a');
dosolve = true;
else
dosolve = false;
end
var = c+d*a/(1-e*a);
for K = 1:N
var = simplify(c+d*(var)/(1-e*var));
end
if dosolve
A = solve(var);
else
A = var;
end
end
function A = calculate_a_numerically(a)
var = c+d*a/(1-e*a);
for K = 1:N
var = c+d*(var)/(1-e*var);
end
%A = [real(var), imag(var)];
A = norm(var);
end
end
Plus de réponses (0)
Voir également
Catégories
En savoir plus sur Conversion Between Symbolic and Numeric dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!