R2019A "Dirac" function is now slow
3 次查看(过去 30 天)
显示 更早的评论
I noticed one of my scripts that repeatedly calls on a function containing MATLAB's dirac function now runs 100% slower compared to R2018b. After tracking down the reason, it seems the dirac function was updated in R2019A. Previously, it performed a check like this:
if ~isequal(round(n), n) || any(~isinfinite(n(:))) || ~isreal(n) || any(n(:) < 0)
error(message('symbolic:dirac:ExpectingNonNegativeInteger1'));
end
Now, the same lines of code read like this:
if ~isequal(round(n), n) || ~sym.isAllFinite(n(:)) || ~isreal(n) || any(n(:) < 0)
error(message('symbolic:dirac:ExpectingNonNegativeInteger1'));
end
The slowdown is being caused by the ~sym.isAllFinite(n(:)), where it appears to be calling on symengine every single one of my (8K+) iterations. Is there a way to speeed this up, or to revert back to previous functionality?
Of note, the function being called, which contains the dirac function, was originally generated using a symbolic derrivative, which was then converted to a matlab function using "matlabFunction".
Thanks!
2 个评论
Walter Roberson
2019-6-4
You could create a local copy of the function.
Somes it makes sense to replace dirac with piecewise and use matlabFunction with File output (matlabFunction cannot convert piecewise for anonymous functions.) This does restrict the input to be scalar, but on the other hand it can permit simplifications, sometimes large simplifications.
Or sometimes it just makes sense to transform x*dirac(expression) to (expression == 0).*x provided that x can never be infinity. This can be a bit tricky to do right automatically, but the new R2019a https://www.mathworks.com/help/symbolic/sym.mapsymtype.html can help. Still, sometimes it is just easier to matlabFunction with file output and edit the result to stick in an anonymous function that maps dirac to @(x) x==0
x == 0 (producing 0 or 1) is of course not the real way that dirac is defined: dirac is defined as returning infinity at 0. But dirac as used in practice in integration has an area of 1 at the one point, so value * dirac(expression) inside integration expresses that the contrabution when the expression is exactly 0 is the value and 0 at any other location.
dirac with matlabFunction gets a bit questionable since when processed numerically it contributes either 0 or infinity and infinity times whatever it is multiplied by is infinity and those infinities tend to "poison" the calculations. If you are using dirac() with integral() then you need to understand the limitations: if integral() does not happen to evaluate at exactly the matching value then there will be no contribution, and if it does evaluate at exactly the matching value you will get an infinity. integral() does not know anything about the special properties of dirac.
回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Assumptions 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!