SymbolicUtils.jl
SymbolicUtils.jl copied to clipboard
lazy evaluation of rational powers
Rational powers are currently eagerly evaluated, so that, for example,
using SymbolicUtils
@syms x
(2x) ^ (1//2) == 1.414… * x^(1//2)
simplify(term(^, 2, 1//2)) == 1.414…
and so on. While this might be intentional, it often causes precision loss and makes many analytical expressions rather ugly.
This PR adds branches to basicsymbolic and ^ to prevent evaluation of powers if the base is a literal number and the exponent is a rational. Integer or float exponents still get evaluated.
With this PR, we therefore have behavior like
(2x) ^ (1//2) == 2^(1//2) * x^(1//2)
simplify(term(^, 2, 1//2)) == 2^(1//2)
simplify(term(^, 1//3, 2)) == 1//9
simplify(term(^, 2, 0.5)) == 1.414…
However, there is a small quirk. Currently (2x) ^ 2 results in (4//1) * x^2, i.e. the integer prefactor is converted to a rational, due to the behavior of the unstable_pow function. I am not sure if this is intentional and I did not follow this conversion in the code in this PR. This means with this PR and a rational exponent, we have (2x) ^ (2//1) == 4 * x^(2//1). I guess if this PR gets merged, this behavior should be made consistent, one way or another.
I am curious if this all sounds like a reasonable change, or if there other reasons why immediate evaluation of all powers is preferable — please let me know what you think!
Benchmark Results
| master | e06f2c78ec761e... | master/e06f2c78ec761e... | |
|---|---|---|---|
| overhead/acrule/a+2 | 0.728 ± 0.016 μs | 0.757 ± 0.019 μs | 0.962 |
| overhead/acrule/a+2+b | 0.698 ± 0.013 μs | 0.725 ± 0.017 μs | 0.962 |
| overhead/acrule/a+b | 0.251 ± 0.0089 μs | 0.258 ± 0.0097 μs | 0.975 |
| overhead/acrule/noop:Int | 25.1 ± 0.92 ns | 26.2 ± 0.91 ns | 0.955 |
| overhead/acrule/noop:Sym | 0.0365 ± 0.005 μs | 0.0368 ± 0.0054 μs | 0.992 |
| overhead/rule/noop:Int | 0.0441 ± 0.0012 μs | 0.0443 ± 0.00084 μs | 0.997 |
| overhead/rule/noop:Sym | 0.0549 ± 0.0023 μs | 0.0548 ± 0.003 μs | 1 |
| overhead/rule/noop:Term | 0.0547 ± 0.0022 μs | 0.055 ± 0.003 μs | 0.994 |
| overhead/ruleset/noop:Int | 0.128 ± 0.0042 μs | 0.129 ± 0.0032 μs | 0.99 |
| overhead/ruleset/noop:Sym | 0.148 ± 0.0041 μs | 0.16 ± 0.0066 μs | 0.927 |
| overhead/ruleset/noop:Term | 3.12 ± 0.12 μs | 3.09 ± 0.1 μs | 1.01 |
| overhead/simplify/noop:Int | 0.144 ± 0.004 μs | 0.14 ± 0.0032 μs | 1.03 |
| overhead/simplify/noop:Sym | 0.158 ± 0.0055 μs | 0.159 ± 0.0065 μs | 0.995 |
| overhead/simplify/noop:Term | 0.0354 ± 0.0024 ms | 0.0378 ± 0.0022 ms | 0.936 |
| overhead/simplify/randterm (+, *):serial | 0.0838 ± 0.0012 s | 0.0897 ± 0.00082 s | 0.935 |
| overhead/simplify/randterm (+, *):thread | 0.0503 ± 0.03 s | 0.0518 ± 0.029 s | 0.97 |
| overhead/simplify/randterm (/, *):serial | 0.209 ± 0.0067 ms | 0.223 ± 0.0078 ms | 0.939 |
| overhead/simplify/randterm (/, *):thread | 0.236 ± 0.0075 ms | 0.254 ± 0.0088 ms | 0.929 |
| overhead/substitute/a | 0.0582 ± 0.0014 ms | 0.0576 ± 0.0014 ms | 1.01 |
| overhead/substitute/a,b | 0.0511 ± 0.0015 ms | 0.0515 ± 0.0014 ms | 0.993 |
| overhead/substitute/a,b,c | 16.9 ± 0.61 μs | 17.6 ± 0.73 μs | 0.963 |
| polyform/easy_iszero | 28.7 ± 1.7 μs | 29.5 ± 1.7 μs | 0.972 |
| polyform/isone | 2.79 ± 0.01 ns | 2.79 ± 0.01 ns | 0.997 |
| polyform/iszero | 1.11 ± 0.03 ms | 1.12 ± 0.032 ms | 0.991 |
| polyform/simplify_fractions | 1.61 ± 0.043 ms | 1.6 ± 0.044 ms | 1.01 |
| time_to_load | 2.1 ± 0.01 s | 2.13 ± 0.023 s | 0.988 |
Benchmark Plots
A plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR. Go to "Actions"->"Benchmark a pull request"->[the most recent run]->"Artifacts" (at the bottom).
Done! Let me know if there is anything else.
:warning: Please install the to ensure uploads and comments are reliably processed by Codecov.
Codecov Report
All modified and coverable lines are covered by tests :white_check_mark:
Project coverage is 82.07%. Comparing base (
0288135) to head (2daeb7e). Report is 3 commits behind head on master.
:exclamation: Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@ Coverage Diff @@
## master #641 +/- ##
==========================================
+ Coverage 81.86% 82.07% +0.20%
==========================================
Files 16 16
Lines 1908 1919 +11
==========================================
+ Hits 1562 1575 +13
+ Misses 346 344 -2
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.